diff options
author | Anders Svensson <[email protected]> | 2012-08-22 16:45:31 +0200 |
---|---|---|
committer | Anders Svensson <[email protected]> | 2012-08-24 19:01:47 +0200 |
commit | b1cdee0b11c6fde89ba586b1c04724daf4a96a07 (patch) | |
tree | b8792510c06709e6d6f1c53c3584717e0e73f67a | |
parent | cfea5eea406ba3af96588ff458e55de9a149d9c5 (diff) | |
download | otp-b1cdee0b11c6fde89ba586b1c04724daf4a96a07.tar.gz otp-b1cdee0b11c6fde89ba586b1c04724daf4a96a07.tar.bz2 otp-b1cdee0b11c6fde89ba586b1c04724daf4a96a07.zip |
Add events for watchdog state transitions
-rw-r--r-- | lib/diameter/doc/src/diameter.xml | 13 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_service.erl | 8 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_watchdog.erl | 48 |
3 files changed, 60 insertions, 9 deletions
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 93e2603c10..4dcbac4889 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -692,6 +692,19 @@ The packet record contains the CEA in question.</p> </taglist> </item> +<tag><c>{watchdog, Ref, PeerRef, {From, To}, Config}</c></tag> +<item> +<code> +Ref = transport_ref() +PeerRef = diameter_app:peer_ref() +From, To = initial | okay | suspect | down | reopen +Config = {connect|listen, [transport_opt()]} +</code> + +<p> +An RFC 3539 watchdog state machine has changed state.</p> +</item> + </taglist> <p> diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 3dfdcee2b2..c9c3179630 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -516,6 +516,14 @@ transition({reconnect, Pid}, S) -> reconnect(Pid, S), ok; +%% Watchdog is sending notification of a state transition. +transition({watchdog, Pid, {TPid, From, To}}, #state{service_name = SvcName, + peerT = PeerT}) -> + #peer{ref = Ref, type = T, options = Opts} + = fetch(PeerT, Pid), + send_event(SvcName, {watchdog, Ref, TPid, {From, To}, {T, Opts}}), + ok; + %% Monitor process has died. Just die with a reason that tells %% diameter_config about the happening. If a cleaner shutdown is %% required then someone should stop us. diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index fb22fd8275..b615bed860 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2012. 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 @@ -54,7 +54,7 @@ %% number of DWAs received during reopen %% end PCB parent = self() :: pid(), - transport :: pid(), + transport :: pid() | undefined, tref :: reference(), %% reference for current watchdog timer message_data}). %% term passed into diameter_service with message @@ -64,6 +64,14 @@ %% that a failed capabilities exchange produces the desired exit %% reason. +-spec start(Type, {RecvData, Opts, SvcName, Svc}) + -> pid() + when Type :: {connect|accept, reference()}, + RecvData :: term(), + Opts :: list(), + SvcName :: term(), + Svc :: #diameter_service{}. + start({_,_} = Type, T) -> Ref = make_ref(), {ok, Pid} = diameter_watchdog_sup:start_child({Ref, {Type, self(), T}}), @@ -102,7 +110,7 @@ i({_, Pid, _} = T) -> %% from old code erlang:monitor(process, Pid), make_state(T). -make_state({T, Pid, {ConnT, +make_state({T, Pid, {RecvData, Opts, SvcName, #diameter_service{applications = Apps, @@ -116,7 +124,7 @@ make_state({T, Pid, {ConnT, tw = proplists:get_value(watchdog_timer, Opts, ?DEFAULT_TW_INIT), - message_data = {ConnT, SvcName, Apps}}. + message_data = {RecvData, SvcName, Apps}}. %% handle_call/3 @@ -134,14 +142,36 @@ handle_info(T, State) -> case transition(T, State) of ok -> {noreply, State}; - #watchdog{status = X} = S -> - ?LOGC(X =/= State#watchdog.status, transition, X), + #watchdog{} = S -> + event(State, S), {noreply, S}; stop -> ?LOG(stop, T), + event(State, State#watchdog{status = down}), {stop, {shutdown, T}, State} end. +event(#watchdog{status = T}, #watchdog{status = T}) -> + ok; + +event(#watchdog{transport = undefined}, #watchdog{transport = undefined}) -> + ok; + +event(#watchdog{status = From, transport = F, parent = Pid}, + #watchdog{status = To, transport = T}) -> + E = {tpid(F,T), From, To}, + notify(Pid, E), + ?LOG(transition, {self(), E}). + +tpid(_, Pid) + when is_pid(Pid) -> + Pid; +tpid(Pid, _) -> + Pid. + +notify(Pid, E) -> + Pid ! {watchdog, self(), E}. + %% terminate/2 terminate(_, _) -> @@ -251,8 +281,8 @@ transition({'DOWN', _, process, TPid, _}, status = initial}) -> stop; -transition({'DOWN', _, process, Pid, _}, - #watchdog{transport = Pid} +transition({'DOWN', _, process, TPid, _}, + #watchdog{transport = TPid} = S) -> failover(S), close(S), @@ -385,7 +415,7 @@ recv(Name, Pkt, S) -> rcv(Name, Pkt, S), NS catch - throw: {?MODULE, throwaway, #watchdog{} = NS} -> + {?MODULE, throwaway, #watchdog{} = NS} -> NS end. |