summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2020-12-04 17:35:59 +0100
committerErlang/OTP <otp@erlang.org>2020-12-04 17:35:59 +0100
commit9d0c7651a59fff8427488a77a4b26d2c876ccc9d (patch)
tree417e3c0322a0070c1c3d23309021b1299fddd059
parent7d81561c87785966c1b053afd35d3e861649472a (diff)
parentce3dc7a30fe12fbd2cd01221c49fd2df4b83dcca (diff)
downloaderlang-9d0c7651a59fff8427488a77a4b26d2c876ccc9d.tar.gz
Merge branch 'bmk/snmp/agent/20201201/serialize_notifications/OTP-17022' into maint-22
* bmk/snmp/agent/20201201/serialize_notifications/OTP-17022: [snmp|agent|doc] Add text about the new (extended) multi-threaded option [snmp|agent|test] Add test cases for extended multi-threaded agent [snmp|agent] Introduce notification specific worker
-rw-r--r--lib/snmp/doc/src/snmp_app.xml46
-rw-r--r--lib/snmp/doc/src/snmp_config.xml31
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl119
-rw-r--r--lib/snmp/src/misc/snmp_verbosity.erl4
-rw-r--r--lib/snmp/test/snmp_agent_SUITE.erl109
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl18
6 files changed, 224 insertions, 103 deletions
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index b080301143..b4c1392b71 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -188,22 +188,46 @@ in the snmp_config file!
<tag><marker id="agent_orig_disco_opts"></marker>
<c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
<item>
- <p><c>agent_originating_discovery_opt() =
- {enable, boolean()}</c></p>
- <p>These are options effecting discovery <c>originating</c> in this
- agent. </p>
- <p>The default values for the <c>originating</c>
- discovery options are: </p>
- <list type="bulleted">
- <item>enable: <c>true</c></item>
+ <p><c>agent_originating_discovery_opt() = {enable, boolean()}</c></p>
+ <p>These are options effecting discovery <c>originating</c> in this
+ agent. </p>
+ <p>The default values for the <c>originating</c>
+ discovery options are: </p>
+ <list type="bulleted">
+ <item>enable: <c>true</c></item>
</list>
</item>
<tag><marker id="agent_mt"></marker>
- <c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
+ <c><![CDATA[multi_threaded() = bool() | extended <optional>]]></c></tag>
<item>
- <p>If <c>true</c>, the agent is multi-threaded, with one
- thread for each get request. </p>
+ <p>If <c>true</c> (or <c>extended</c>), the agent is multi-threaded,
+ with one thread for each get request.</p>
+ <p>The value <c>extended</c> means that a special 'process'
+ is also created intended to handle <em>all</em> notifications. </p>
+ <list>
+ <item>
+ <p><c>true</c> - One worker dedicated to 'set-requests' and one
+ (main) worker for all other requests ('get-request' and
+ notifications).</p>
+ <p>If the 'main' worker is busy, a temporary process is
+ spawned to handle that job ('get-request' or notification). </p>
+ </item>
+ <item>
+ <p><c>extended</c> - One worker dedicated to 'set-requests',
+ one worker dedicated to notifications and one
+ (main) worker for all 'get-requests'. </p>
+ <p>If the 'main' worker is busy, a temporary process is
+ spawned to handle that 'get-request'. </p>
+ </item>
+ </list>
+ <note>
+ <p>Even with multi-threaded set to <c>extended</c>
+ there is still a risk for 'reorder' when sending inform-requsts,
+ which require a response (and may therefor require resending). </p>
+ <p>Also, there is of course no way to guarantee order once the
+ package is on the network. </p>
+ </note>
<p>Default is <c>false</c>.</p>
</item>
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index 8ced577a8a..ea8973f4f8 100644
--- a/lib/snmp/doc/src/snmp_config.xml
+++ b/lib/snmp/doc/src/snmp_config.xml
@@ -184,10 +184,35 @@
</item>
<tag><marker id="agent_mt"></marker>
- <c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
+ <c><![CDATA[multi_threaded() = bool() | extended<optional>]]></c></tag>
<item>
- <p>If <c>true</c>, the agent is multi-threaded, with one
- thread for each get request. </p>
+ <p>If <c>true</c> (or <c>extended</c>), the agent is multi-threaded,
+ with one thread for each get request. </p>
+ <p>The value <c>extended</c> means that a special 'process'
+ is also created intended to handle <em>all</em> notifications. </p>
+ <list>
+ <item>
+ <p><c>true</c> - One worker dedicated to 'set-requests' and one
+ (main) worker for all other requests ('get-request' and
+ notifications).</p>
+ <p>If the 'main' worker is busy, a temporary process is
+ spawned to handle that job ('get-request' or notification). </p>
+ </item>
+ <item>
+ <p><c>extended</c> - One worker dedicated to 'set-requests',
+ one worker dedicated to notifications and one
+ (main) worker for all 'get-requests'. </p>
+ <p>If the 'main' worker is busy, a temporary process is
+ spawned to handle that 'get-request'. </p>
+ </item>
+ </list>
+ <note>
+ <p>Even with multi-threaded set to <c>extended</c>
+ there is still a risk for 'reorder' when sending inform-requsts,
+ which require a response (and may therefor require resending). </p>
+ <p>Also, there is of course no way to guarantee order once the
+ package is on the network. </p>
+ </note>
<p>Default is <c>false</c>.</p>
</item>
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index cc3bef15af..649a54b844 100644
--- a/lib/snmp/src/agent/snmpa_agent.erl
+++ b/lib/snmp/src/agent/snmpa_agent.erl
@@ -63,7 +63,7 @@
-export([get_request_limit/1, set_request_limit/2]).
-export([invalidate_ca_cache/0]).
-export([increment_counter/3]).
--export([restart_worker/1, restart_set_worker/1]).
+-export([restart_worker/1, restart_set_worker/1, restart_notif_worker/1]).
%% For backward compatibillity
-export([send_trap/6, send_trap/7]).
@@ -71,7 +71,7 @@
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, tr_var/2, tr_varbind/1,
- handle_pdu/8, worker/2, worker_loop/1,
+ handle_pdu/8, worker/4, worker_loop/2,
do_send_trap/7, do_send_trap/8]).
%% <BACKWARD-COMPAT>
-export([handle_pdu/7,
@@ -177,6 +177,7 @@
worker,
worker_state = ready,
set_worker,
+ notif_worker,
multi_threaded,
ref,
vsns,
@@ -249,6 +250,9 @@ restart_worker(Agent) ->
restart_set_worker(Agent) ->
call(Agent, restart_set_worker).
+restart_notif_worker(Agent) ->
+ call(Agent, restart_notif_worker).
+
get_log_type(Agent) ->
call(Agent, get_log_type).
@@ -391,11 +395,12 @@ do_init(Prio, Parent, Ref, Options) ->
put(net_if, NetIfPid),
put(mibserver, MibPid),
process_flag(trap_exit, true),
- {Worker, SetWorker} = workers_start(MultiT),
+ {Worker, SetWorker, NotifWorker} = workers_start(MultiT),
{ok, #state{type = Type,
parent = Parent,
worker = Worker,
set_worker = SetWorker,
+ notif_worker = NotifWorker,
multi_threaded = MultiT,
ref = Ref,
vsns = Vsns,
@@ -975,9 +980,13 @@ handle_info({'EXIT', Pid, Reason}, #state{worker = Pid} = S) ->
NewWorker = worker_start(),
{noreply, S#state{worker = NewWorker}};
handle_info({'EXIT', Pid, Reason}, #state{set_worker = Pid} = S) ->
- ?vlog("set-worker (~p) exited -> create new ~n ~p", [Pid,Reason]),
+ ?vlog("set-worker (~p) exited -> create new ~n ~p", [Pid, Reason]),
NewWorker = set_worker_start(),
{noreply, S#state{set_worker = NewWorker}};
+handle_info({'EXIT', Pid, Reason}, #state{notif_worker = Pid} = S) ->
+ ?vlog("notif-worker (~p) exited -> create new ~n ~p", [Pid, Reason]),
+ NewWorker = notif_worker_start(),
+ {noreply, S#state{notif_worker = NewWorker}};
handle_info({'EXIT', Pid, Reason}, #state{parent = Pid} = S) ->
?vlog("parent (~p) exited for reason ~n~p", [Pid,Reason]),
{stop, {parent_died, Reason}, S};
@@ -1415,13 +1424,17 @@ handle_cast({verbosity, Verbosity}, S) ->
?vlog("verbosity: ~p -> ~p",[get(verbosity), Verbosity]),
put(verbosity,snmp_verbosity:validate(Verbosity)),
case S#state.worker of
- Pid when is_pid(Pid) -> Pid ! ?mk_verbosity_wreq(Verbosity);
+ Pid1 when is_pid(Pid1) -> Pid1 ! ?mk_verbosity_wreq(Verbosity);
_ -> ok
end,
case S#state.set_worker of
Pid2 when is_pid(Pid2) -> Pid2 ! ?mk_verbosity_wreq(Verbosity);
_ -> ok
end,
+ case S#state.notif_worker of
+ Pid3 when is_pid(Pid3) -> Pid3 ! ?mk_verbosity_wreq(Verbosity);
+ _ -> ok
+ end,
{noreply, S};
handle_cast({sub_agents_verbosity,Verbosity}, S) ->
@@ -1447,14 +1460,16 @@ handle_cast(Msg, S) ->
{noreply, S}.
-terminate(shutdown, #state{worker = Worker,
- set_worker = SetWorker,
- backup = Backup,
+terminate(shutdown, #state{worker = Worker,
+ set_worker = SetWorker,
+ notif_worker = NotifWorker,
+ backup = Backup,
ref = Ref}) ->
%% Ordered shutdown - stop misc-workers, net_if, mib-server and note-store.
backup_server_stop(Backup),
worker_stop(Worker, 100),
worker_stop(SetWorker, 100),
+ worker_stop(NotifWorker, 100),
snmpa_misc_sup:stop_net_if(Ref),
snmpa_misc_sup:stop_mib_server(Ref);
terminate(_Reason, _S) ->
@@ -1600,20 +1615,26 @@ backup_server_stop(_) ->
ok.
+workers_start(extended) ->
+ ?vdebug("start worker, set-worker and notif-worker", []),
+ {worker_start(), set_worker_start(), notif_worker_start()};
workers_start(true) ->
- ?vdebug("start worker and set-worker",[]),
- {worker_start(), set_worker_start()};
+ ?vdebug("start worker and set-worker", []),
+ {worker_start(), set_worker_start(), undefined};
workers_start(_) ->
- {undefined, undefined}.
+ {undefined, undefined, undefined}.
worker_start() ->
- worker_start(get()).
+ worker_start(mw, true, get()).
set_worker_start() ->
- worker_start([{master, self()} | get()]).
+ worker_start(sw, false, [{master, self()} | get()]).
+
+notif_worker_start() ->
+ worker_start(nw, false, [{master, self()} | get()]).
-worker_start(Dict) ->
- proc_lib:spawn_link(?MODULE, worker, [self(), Dict]).
+worker_start(SName, Report, Dict) ->
+ proc_lib:spawn_link(?MODULE, worker, [self(), SName, Report, Dict]).
%% worker_stop(Pid) ->
%% worker_stop(Pid, infinity).
@@ -1783,13 +1804,13 @@ do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
LocalEngineID, ExtraInfo, get(net_if)).
-worker(Master, Dict) ->
+worker(Master, SName, Report, Dict) ->
lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict),
- put(sname, worker_short_name(get(sname))),
+ put(sname, worker_short_name(get(sname), SName)),
?vlog("starting",[]),
- worker_loop(Master).
+ worker_loop(Master, Report).
-worker_loop(Master) ->
+worker_loop(Master, Report) ->
Res =
receive
#wrequest{cmd = handle_pdu,
@@ -1813,7 +1834,7 @@ worker_loop(Master) ->
C:E:S ->
exit({worker_crash, Req, C, E, S})
end,
- Master ! worker_available,
+ worker_maybe_announce_available(Master, Report),
HandlePduRes; % For debugging...
@@ -1840,7 +1861,7 @@ worker_loop(Master) ->
C:E:S ->
exit({worker_crash, Req, C, E, S})
end,
- Master ! worker_available,
+ worker_maybe_announce_available(Master, Report),
SendTrapRes; % For debugging...
@@ -1853,8 +1874,10 @@ worker_loop(Master) ->
#wrequest{cmd = terminate} ->
?vtrace("worker_loop -> received terminate request", []),
exit(normal);
-
-
+
+
+
+
%% *************************************************************
%%
%% Kept for backward compatibillity reasons
@@ -1904,7 +1927,12 @@ worker_loop(Master) ->
end,
?vtrace("worker_loop -> wrap with"
"~n ~p", [Res]),
- ?MODULE:worker_loop(Master).
+ ?MODULE:worker_loop(Master, Report).
+
+worker_maybe_announce_available(Master, true) ->
+ Master ! worker_available;
+worker_maybe_announce_available(_Master, _Report) ->
+ ok.
%%-----------------------------------------------------------------
@@ -2186,6 +2214,13 @@ do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds,
Recv, Vbs, LocalEngineID, ExtraInfo,
get(net_if)),
{ok, S};
+ master_agent when (S#state.multi_threaded =:= extended) ->
+ %% Send to main worker
+ ?vtrace("do_handle_send_trap -> send to notif-worker",[]),
+ S#state.notif_worker ! ?mk_send_trap_wreq(TrapRec, NotifyName,
+ ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo),
+ {ok, S};
master_agent when S#state.worker_state =:= busy ->
%% Main worker busy => create new worker
?vtrace("do_handle_send_trap -> main worker busy: "
@@ -2195,7 +2230,7 @@ do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds,
{ok, S};
master_agent ->
%% Send to main worker
- ?vtrace("do_handle_send_trap -> send to main worker",[]),
+ ?vtrace("do_handle_send_trap -> send to main worker", []),
S#state.worker ! ?mk_send_trap_wreq(TrapRec, NotifyName,
ContextName, Recv, Vbs,
LocalEngineID, ExtraInfo),
@@ -3225,8 +3260,10 @@ mapfoldl(_F, _Eas, Accu, []) -> {Accu,[]}.
short_name(none) -> ma;
short_name(_Pid) -> sa.
-worker_short_name(ma) -> maw;
-worker_short_name(_) -> saw.
+worker_short_name(ma, mw) -> mamw;
+worker_short_name(ma, sw) -> masw;
+worker_short_name(ma, nw) -> manw;
+worker_short_name(_, _) -> saw.
trap_sender_short_name(ma) -> mats;
trap_sender_short_name(_) -> sats.
@@ -3318,27 +3355,33 @@ handle_set_request_limit(_, _) ->
{error, not_supported}.
-agent_info(#state{worker = W, set_worker = SW}) ->
- case (catch get_agent_info(W, SW)) of
+agent_info(#state{worker = W, set_worker = SW, notif_worker = NW}) ->
+ case (catch get_agent_info(W, SW, NW)) of
Info when is_list(Info) ->
Info;
E ->
[{error, E}]
end.
-get_agent_info(W, SW) ->
+get_agent_info(W, SW, NW) ->
MASz = proc_mem(self()),
- WSz = proc_mem(W),
- SWSz = proc_mem(SW),
ATSz = tab_mem(snmp_agent_table),
CCSz = tab_mem(snmp_community_cache),
VacmSz = tab_mem(snmpa_vacm),
- [{process_memory, [{master_agent, MASz},
- {worker, WSz},
- {set_worker, SWSz}]},
- {db_memory, [{agent, ATSz},
- {community_cache, CCSz},
- {vacm, VacmSz}]}].
+ [{process_memory,
+ [{master_agent, MASz}] ++
+ process_memory(worker, W) ++
+ process_memory(set_worker, SW) ++
+ process_memory(notif_worker, NW)},
+ {db_memory,
+ [{agent, ATSz},
+ {community_cache, CCSz},
+ {vacm, VacmSz}]}].
+
+process_memory(Tag, P) when is_pid(P) ->
+ [{Tag, proc_mem(P)}];
+process_memory(_, _) ->
+ [].
proc_mem(P) when is_pid(P) ->
case (catch erlang:process_info(P, memory)) of
diff --git a/lib/snmp/src/misc/snmp_verbosity.erl b/lib/snmp/src/misc/snmp_verbosity.erl
index 9bc3e2762f..0572ebea03 100644
--- a/lib/snmp/src/misc/snmp_verbosity.erl
+++ b/lib/snmp/src/misc/snmp_verbosity.erl
@@ -100,7 +100,9 @@ image_of_verbosity(_) -> "".
%% ShortName
image_of_sname(ma) -> "MASTER-AGENT";
-image_of_sname(maw) -> io_lib:format("MASTER-AGENT-worker(~p)",[self()]);
+image_of_sname(mamw) -> io_lib:format("MASTER-AGENT-main_worker(~p)",[self()]);
+image_of_sname(masw) -> io_lib:format("MASTER-AGENT-set_worker(~p)",[self()]);
+image_of_sname(manw) -> io_lib:format("MASTER-AGENT-notif_worker(~p)",[self()]);
image_of_sname(madis) -> io_lib:format("MASTER-AGENT-discovery_inform_sender(~p)",
[self()]);
image_of_sname(mais) -> io_lib:format("MASTER-AGENT-inform_sender(~p)",
diff --git a/lib/snmp/test/snmp_agent_SUITE.erl b/lib/snmp/test/snmp_agent_SUITE.erl
index 2a6cfbedbe..d433692b0a 100644
--- a/lib/snmp/test/snmp_agent_SUITE.erl
+++ b/lib/snmp/test/snmp_agent_SUITE.erl
@@ -204,7 +204,7 @@
v3_sha_auth/1,
v3_des_priv/1,
- %% all_tcs - test_multi_threaded
+ %% all_tcs - test_multi_threaded, test_multi_threaded_ext
multi_threaded/1,
mt_trap/1,
@@ -319,7 +319,7 @@
db_notify_client_test/0,
notify/2,
multi_threaded_test/0,
- mt_trap_test/1,
+ mt_trap_test/2,
types_v2_test/0,
implied_test/1,
sparse_table_test/0,
@@ -535,6 +535,7 @@ groups() ->
{test_v3, [], v3_cases()},
{test_v3_ipv6, [], v3_cases_ipv6()},
{test_multi_threaded, [], mt_cases()},
+ {test_multi_threaded_ext, [], mt_cases()},
{multiple_reqs, [], mul_cases()},
{multiple_reqs_2, [], mul_cases_2()},
{multiple_reqs_3, [], mul_cases_3()},
@@ -568,6 +569,7 @@ all_cases() ->
{group, test_v1_v2_ipv6},
{group, test_v3_ipv6},
{group, test_multi_threaded},
+ {group, test_multi_threaded_ext},
{group, mib_storage},
{group, tickets1}
].
@@ -654,7 +656,9 @@ init_per_group(multiple_reqs_2 = GroupName, Config) ->
init_per_group(multiple_reqs_3 = GroupName, Config) ->
init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config));
init_per_group(test_multi_threaded = GroupName, Config) ->
- init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config), true);
+init_per_group(test_multi_threaded_ext = GroupName, Config) ->
+ init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config), extended);
init_per_group(test_v3 = GroupName, Config) ->
case snmp_test_lib:crypto_start() of
ok ->
@@ -764,49 +768,51 @@ end_per_group(v2_inform, Config) ->
end_per_group(v3_inform, Config) ->
finish_v3_inform(Config);
end_per_group(multiple_reqs, Config) ->
- finish_mul(Config);
+ finish_mul(Config);
end_per_group(multiple_reqs_2, Config) ->
finish_mul(Config);
end_per_group(multiple_reqs_3, Config) ->
finish_mul(Config);
end_per_group(test_multi_threaded, Config) ->
- finish_mt(Config);
+ finish_mt(Config);
+end_per_group(test_multi_threaded_ext, Config) ->
+ finish_mt(Config);
end_per_group(test_v3_ipv6, Config) ->
- finish_v3(Config);
+ finish_v3(Config);
end_per_group(test_v1_v2_ipv6, Config) ->
- finish_v1_v2(Config);
+ finish_v1_v2(Config);
end_per_group(test_v2_ipv6, Config) ->
- finish_v2(Config);
+ finish_v2(Config);
end_per_group(test_v1_ipv6, Config) ->
- finish_v1(Config);
+ finish_v1(Config);
end_per_group(test_v3, Config) ->
- finish_v3(Config);
+ finish_v3(Config);
end_per_group(test_v1_v2, Config) ->
- finish_v1_v2(Config);
+ finish_v1_v2(Config);
end_per_group(test_v2, Config) ->
- finish_v2(Config);
+ finish_v2(Config);
end_per_group(test_v1, Config) ->
- finish_v1(Config);
+ finish_v1(Config);
end_per_group(misc, Config) ->
- finish_misc(Config);
+ finish_misc(Config);
end_per_group(mib_storage_varm_mnesia, Config) ->
- finish_varm_mib_storage_mnesia(Config);
+ finish_varm_mib_storage_mnesia(Config);
end_per_group(mib_storage_varm_dets, Config) ->
- finish_varm_mib_storage_dets(Config);
+ finish_varm_mib_storage_dets(Config);
end_per_group(mib_storage_size_check_mnesia, Config) ->
- finish_size_check_msm(Config);
+ finish_size_check_msm(Config);
end_per_group(mib_storage_size_check_dets, Config) ->
- finish_size_check_msd(Config);
+ finish_size_check_msd(Config);
end_per_group(mib_storage_size_check_ets, Config) ->
- finish_size_check_mse(Config);
+ finish_size_check_mse(Config);
end_per_group(mib_storage_mnesia, Config) ->
- finish_mib_storage_mnesia(Config);
+ finish_mib_storage_mnesia(Config);
end_per_group(mib_storage_dets, Config) ->
- finish_mib_storage_dets(Config);
+ finish_mib_storage_dets(Config);
end_per_group(mib_storage_ets, Config) ->
- finish_mib_storage_ets(Config);
+ finish_mib_storage_ets(Config);
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
@@ -1040,8 +1046,8 @@ start_v3_agent(Config, Opts) ->
start_bilingual_agent(Config) ->
?ALIB:start_bilingual_agent(Config).
-start_multi_threaded_agent(Config) when is_list(Config) ->
- ?ALIB:start_mt_agent(Config).
+start_multi_threaded_agent(Config, MT) when is_list(Config) ->
+ [{multi_threaded, MT} | ?ALIB:start_mt_agent(Config, MT)].
stop_agent(Config) ->
?ALIB:stop_agent(Config).
@@ -2117,7 +2123,7 @@ mt_cases() ->
mt_trap
].
-init_mt(Config) when is_list(Config) ->
+init_mt(Config, MT) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
AgentConfDir = ?config(agent_conf_dir, Config),
@@ -2125,7 +2131,7 @@ init_mt(Config) when is_list(Config) ->
Ip = ?config(ip, Config),
?line ok = config([v2], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
+ [{vsn, v2} | start_multi_threaded_agent(Config, MT)].
finish_mt(Config) when is_list(Config) ->
delete_tables(),
@@ -2290,10 +2296,11 @@ mt_trap(Config) when is_list(Config) ->
?P(mt_trap),
init_case(Config),
MA = whereis(snmp_master_agent),
+ MT = ?config(multi_threaded, Config),
?line load_master("Test1"),
?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
+ try_test(mt_trap_test, [MA, MT]),
?line unload_master("TestTrapv2"),
?line unload_master("Test1"),
ok.
@@ -3959,37 +3966,51 @@ multi_threaded_test() ->
?line ?expect1([{[sysLocation,0], "kalle"}]).
%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- ?NPRINT("Testing trap-sending with multi threaded agent..."),
- ?DBG("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []),
+mt_trap_test(MA, MT) ->
+ ?NPRINT("Testing trap-sending with multi threaded (~w) agent...", [MT]),
+ ?IPRINT("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []),
snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?DBG("mt_trap_test(02) -> await v2trap", []),
+ ?IPRINT("mt_trap_test(02) -> await v2trap", []),
?line ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("mt_trap_test(03) -> issue mtTrap (standard trap)", []),
+ %% multi-threaded = true
+ %% This will *lock* the 'main thread' of a multi-threaded agent,
+ %% the worker state will be 'busy'. Therefor when a new request
+ %% arrives a new *temporary* worker will be spawned.
+ ?IPRINT("mt_trap_test(03) -> issue mtTrap (standard trap)", []),
snmpa:send_trap(MA, mtTrap, "standard trap"),
Pid = get_multi_pid(),
- ?DBG("mt_trap_test(04) -> multi pid: ~p. Now request sysUpTime...", [Pid]),
+ ?IPRINT("mt_trap_test(04) -> multi pid: ~p. Now request sysUpTime...", [Pid]),
g([[sysUpTime,0]]),
- ?DBG("mt_trap_test(06) -> await sysUpTime", []),
+ ?IPRINT("mt_trap_test(06) -> await sysUpTime", []),
?line ?expect1([{[sysUpTime,0], any}]),
- ?DBG("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?DBG("mt_trap_test(08) -> await v2trap", []),
- ?line ?expect2(v2trap,
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("mt_trap_test(09) -> send continue to multi-pid", []),
+ %% This will *only* work if multi-threaded is 'true', not 'extended'
+ %% since in the latter case all notifications are serialized through
+ %% a dedicated worker, which is now locked (see above).
+
+ if
+ (MT =:= true) ->
+ ?IPRINT("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?IPRINT("mt_trap_test(08) -> await v2trap", []),
+ ?line ?expect2(v2trap,
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]);
+ true ->
+ ok
+ end,
+
+ ?IPRINT("mt_trap_test(09) -> send continue to multi-pid", []),
Pid ! continue,
- ?DBG("mt_trap_test(10) -> await v2trap", []),
+ ?IPRINT("mt_trap_test(10) -> await v2trap", []),
?line ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?testTrap ++ [2]},
{[multiStr,0], "ok"}]),
- ?DBG("mt_trap_test(11) -> done", []),
+ ?IPRINT("mt_trap_test(11) -> done", []),
ok.
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 6a4c582f36..b3c492e4ce 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -26,7 +26,7 @@
start_v2_agent/1, start_v2_agent/2,
start_v3_agent/1, start_v3_agent/2,
start_bilingual_agent/1, start_bilingual_agent/2,
- start_mt_agent/1, start_mt_agent/2,
+ start_mt_agent/1, start_mt_agent/2, start_mt_agent/3,
stop_agent/1,
%% start_sup/0, stop_sup/2,
@@ -560,12 +560,18 @@ start_bilingual_agent(Config, Opts)
when is_list(Config) andalso is_list(Opts) ->
start_agent(Config, [v1,v2], Opts).
-start_mt_agent(Config) when is_list(Config) ->
- start_agent(Config, [v2], [{multi_threaded, true}]).
-
-start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
- start_agent(Config, [v2], [{multi_threaded, true}|Opts]).
+start_mt_agent(Config) ->
+ start_mt_agent(Config, true, []).
+start_mt_agent(Config, MT) ->
+ start_mt_agent(Config, MT, []).
+
+start_mt_agent(Config, MT, Opts)
+ when is_list(Config) andalso
+ ((MT =:= true) orelse (MT =:= extended)) andalso
+ is_list(Opts) ->
+ start_agent(Config, [v2], [{multi_threaded, MT} | Opts]).
+
start_agent(Config, Vsns) ->
start_agent(Config, Vsns, []).
start_agent(Config, Vsns, Opts) ->