improve keepalie

This commit is contained in:
Feng 2015-10-04 19:43:58 +08:00
parent 273149f633
commit 78288e8088
1 changed files with 37 additions and 38 deletions

View File

@ -23,62 +23,61 @@
%%%
%%% @end
%%%-----------------------------------------------------------------------------
-module(emqttd_keepalive).
-author("Feng Lee <feng@emqtt.io>").
-export([new/3, resume/1, cancel/1]).
-export([start/3, check/1, cancel/1]).
-record(keepalive, {transport,
socket,
recv_oct,
timeout_sec,
timeout_msg,
timer_ref}).
-record(keepalive, {statfun, statval,
tsec, tmsg, tref,
repeat = 0}).
%%------------------------------------------------------------------------------
%% @doc Create a keepalive
%% @doc Start a keepalive
%% @end
%%------------------------------------------------------------------------------
new({Transport, Socket}, TimeoutSec, TimeoutMsg) when TimeoutSec > 0 ->
{ok, [{recv_oct, RecvOct}]} = Transport:getstat(Socket, [recv_oct]),
Ref = erlang:send_after(timer:seconds(TimeoutSec), self(), TimeoutMsg),
#keepalive {transport = Transport,
socket = Socket,
recv_oct = RecvOct,
timeout_sec = TimeoutSec,
timeout_msg = TimeoutMsg,
timer_ref = Ref}.
start(_, 0, _) ->
undefined;
start(StatFun, TimeoutSec, TimeoutMsg) ->
{ok, StatVal} = StatFun(),
#keepalive{statfun = StatFun, statval = StatVal,
tsec = TimeoutSec, tmsg = TimeoutMsg,
tref = timer(TimeoutSec, TimeoutMsg)}.
%%------------------------------------------------------------------------------
%% @doc Try to resume keepalive, called when timeout
%% @doc Check keepalive, called when timeout.
%% @end
%%------------------------------------------------------------------------------
resume(KeepAlive = #keepalive {transport = Transport,
socket = Socket,
recv_oct = RecvOct,
timeout_sec = TimeoutSec,
timeout_msg = TimeoutMsg,
timer_ref = Ref }) ->
{ok, [{recv_oct, NewRecvOct}]} = Transport:getstat(Socket, [recv_oct]),
if
NewRecvOct =:= RecvOct ->
timeout;
true ->
%need?
cancel(Ref),
NewRef = erlang:send_after(timer:seconds(TimeoutSec), self(), TimeoutMsg),
{resumed, KeepAlive#keepalive{recv_oct = NewRecvOct, timer_ref = NewRef}}
check(KeepAlive = #keepalive{statfun = StatFun, statval = LastVal, repeat = Repeat}) ->
case StatFun() of
{ok, NewVal} ->
if NewVal =/= LastVal ->
{ok, resume(KeepAlive#keepalive{statval = NewVal, repeat = 0})};
Repeat < 1 ->
{ok, resume(KeepAlive#keepalive{statval = NewVal, repeat = Repeat + 1})};
true ->
{error, timeout}
end;
{error, Error} ->
{error, Error}
end.
resume(KeepAlive = #keepalive{tsec = TimeoutSec, tmsg = TimeoutMsg}) ->
KeepAlive#keepalive{tref = timer(TimeoutSec, TimeoutMsg)}.
%%------------------------------------------------------------------------------
%% @doc Cancel Keepalive
%% @end
%%------------------------------------------------------------------------------
cancel(#keepalive{timer_ref = Ref}) ->
cancel(Ref);
cancel(#keepalive{tref = TRef}) ->
cancel(TRef);
cancel(undefined) ->
undefined;
cancel(Ref) ->
catch erlang:cancel_timer(Ref).
ok;
cancel(TRef) ->
catch erlang:cancel_timer(TRef).
timer(Sec, Msg) ->
erlang:send_after(timer:seconds(Sec), self(), Msg).