aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/src/base')
-rw-r--r--lib/diameter/src/base/diameter_stats.erl13
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl45
2 files changed, 38 insertions, 20 deletions
diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl
index 64ea082be0..79a5c7b947 100644
--- a/lib/diameter/src/base/diameter_stats.erl
+++ b/lib/diameter/src/base/diameter_stats.erl
@@ -142,9 +142,14 @@ read(Refs, B) ->
L.
to_refdict(L) ->
- lists:foldl(fun({{C,R}, N}, D) -> orddict:append(R, {C,N}, D) end,
- orddict:new(),
- L).
+ lists:foldl(fun append/2, orddict:new(), L).
+
+%% Order both references and counters in the returned list.
+append({{Ctr, Ref}, N}, Dict) ->
+ orddict:update(Ref,
+ fun(D) -> orddict:store(Ctr, N, D) end,
+ [{Ctr, N}],
+ Dict).
%% ---------------------------------------------------------------------------
%% # sum(Refs)
@@ -220,7 +225,7 @@ uptime() ->
%% ----------------------------------------------------------
init([]) ->
- ets:new(?TABLE, [named_table, ordered_set, public]),
+ ets:new(?TABLE, [named_table, set, public, {write_concurrency, true}]),
{ok, #state{}}.
%% ----------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index 55c303dec2..ac03ab1260 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -65,7 +65,10 @@
%% end PCB
parent = self() :: pid(), %% service process
transport :: pid() | undefined, %% peer_fsm process
- tref :: reference(), %% reference for current watchdog timer
+ tref :: reference() %% reference for current watchdog timer
+ | integer() %% monotonic time
+ | tuple() %% now()
+ | undefined,
dictionary :: module(), %% common dictionary
receive_data :: term(),
%% term passed into diameter_service with incoming message
@@ -93,7 +96,7 @@ start({_,_} = Type, T) ->
Ack = make_ref(),
{ok, Pid} = diameter_watchdog_sup:start_child({Ack, Type, self(), T}),
try
- {erlang:monitor(process, Pid), Pid}
+ {monitor(process, Pid), Pid}
after
send(Pid, Ack)
end.
@@ -120,7 +123,7 @@ i({Ack, T, Pid, {RecvData,
#diameter_service{applications = Apps,
capabilities = Caps}
= Svc}}) ->
- erlang:monitor(process, Pid),
+ monitor(process, Pid),
wait(Ack, Pid),
{_, Seed} = diameter_lib:seed(),
random:seed(Seed),
@@ -451,11 +454,12 @@ transition({recv, TPid, Name, Pkt}, #watchdog{transport = TPid} = S) ->
%% Current watchdog has timed out.
transition({timeout, TRef, tw}, #watchdog{tref = TRef} = S) ->
- set_watchdog(timeout(S));
+ set_watchdog(0, timeout(S));
-%% Timer was canceled after message was already sent.
-transition({timeout, _, tw}, #watchdog{}) ->
- ok;
+%% Message has arrived since the timer was started: subtract time
+%% already elapsed from new timer.
+transition({timeout, _, tw}, #watchdog{tref = T0} = S) ->
+ set_watchdog(diameter_lib:micro_diff(T0) div 1000, S);
%% State query.
transition({state, Pid}, #watchdog{status = S}) ->
@@ -531,18 +535,27 @@ role() ->
%% set_watchdog/1
-set_watchdog(#watchdog{tw = TwInit,
- tref = TRef}
- = S) ->
- cancel(TRef),
- S#watchdog{tref = erlang:start_timer(tw(TwInit), self(), tw)};
+%% Timer not yet set.
+set_watchdog(#watchdog{tref = undefined} = S) ->
+ set_watchdog(0, S);
+
+%% Timer already set: start at new one only at expiry.
+set_watchdog(#watchdog{} = S) ->
+ S#watchdog{tref = diameter_lib:now()};
+
set_watchdog(stop = No) ->
No.
-cancel(undefined) ->
- ok;
-cancel(TRef) ->
- erlang:cancel_timer(TRef).
+%% set_watchdog/2
+
+set_watchdog(Ms, #watchdog{tw = TwInit} = S) ->
+ S#watchdog{tref = erlang:start_timer(tw(TwInit, Ms), self(), tw)}.
+
+%% A callback could return anything, so ensure the result isn't
+%% negative. Don't prevent abuse, even though the smallest valid
+%% timeout is 4000.
+tw(TwInit, Ms) ->
+ max(tw(TwInit) - Ms, 0).
tw(T)
when is_integer(T), T >= 6000 ->