1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2014-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%% The reason for this (test) counter server is that the 23%% agent test suite is implemented in such a way that the 24%% agent is started once and then used for several test cases. 25%% Each request is given a request id which *was* generated using 26%% random! It is therefor possible, although unlikely, that a 27%% request may get a request id that has recently been used, 28%% which will cause the agent to silently reject the request. 29%% For this reason, we start this server at the start of the 30%% agent suite and stop it at the end and all request ids are 31%% generated by this server. 32%% 33 34-module(snmp_test_mgr_counter_server). 35 36-export([start/0, stop/0, increment/4]). 37 38-define(SERVER, ?MODULE). 39-define(TAB, snmp_test_mgr_counter_tab). 40 41 42%%%------------------------------------------------------------------- 43%%% API 44%%%------------------------------------------------------------------- 45 46-spec start() -> ok. 47 48start() -> 49 Parent = self(), 50 ReqIdServer = spawn(fun() -> init(Parent) end), 51 receive 52 {ReqIdServer, ok} -> 53 ok; 54 {ReqIdServer, {error, Reason}} -> 55 exit({failed_starting_counter_server, Reason}) 56 after 5000 -> 57 exit(ReqIdServer, kill), % Cleanup, just in case 58 exit({failed_starting_counter_server, timeout}) 59 end. 60 61-spec stop() -> {ok, Counters :: list()} | {error, Reason :: term()}. 62 63stop() -> 64 request(stop). 65 66 67-spec increment(Counter :: atom(), 68 Initial :: non_neg_integer(), 69 Increment :: pos_integer(), 70 Max :: pos_integer()) -> 71 Next :: pos_integer(). 72 73increment(Counter, Initial, Increment, Max) -> 74 Request = {increment, Counter, Initial, Increment, Max}, 75 case request(Request) of 76 {ok, ReqId} -> 77 ReqId; 78 {error, Reason} -> 79 exit(Reason) 80 end. 81 82 83request(Request) -> 84 Id = make_ref(), 85 Msg = {self(), Id, Request}, 86 try 87 begin 88 global:send(?SERVER, Msg), 89 receive 90 {reply, Id, Reply} -> 91 {ok, Reply} 92 end 93 end 94 catch 95 T:E -> 96 {error, {T, E}} 97 end. 98 99 100%%%------------------------------------------------------------------- 101%%% Internal functions 102%%%------------------------------------------------------------------- 103 104init(Parent) -> 105 p("starting"), 106 case global:register_name(?SERVER, self()) of 107 yes -> 108 p("name registration ok"), 109 Parent ! {self(), ok}; 110 no -> 111 p("name registration failed"), 112 Parent ! {self(), registration_failed}, 113 exit(registration_failed) 114 end, 115 ets:new(?TAB, [set, named_table, {keypos, 1}]), 116 loop(). 117 118loop() -> 119 receive 120 {From, Id, {increment, Counter, Initial, Increment, Max}} -> 121 Position = 2, 122 Threshold = Max, 123 SetValue = Initial, 124 UpdateOp = {Position, Increment, Threshold, SetValue}, 125 NextVal = 126 try ets:update_counter(?TAB, Counter, UpdateOp) of 127 Next when is_integer(Next) -> 128 p("increment ~w: (next) ~w", [Counter, Next]), 129 Next 130 catch 131 error:badarg -> 132 %% Oups, first time 133 p("increment ~w: (initial) ~w", [Counter, Initial]), 134 ets:insert(?TAB, {Counter, Initial}), 135 Initial 136 end, 137 From ! {reply, Id, NextVal}, 138 loop(); 139 140 {From, Id, stop} -> 141 p("stop"), 142 Counters = ets:tab2list(?TAB), 143 From ! {reply, Id, Counters}, 144 exit(normal) 145 end. 146 147 148p(F) -> 149 p(F, []). 150 151p(F, A) -> 152 io:format("*** [~s] COUNTER-SERVER [~w] " ++ F ++ "~n", 153 [snmp_test_lib:formated_timestamp(), self() | A]). 154