Current section
Files
Jump to
Current section
Files
src/srv.erl
-module(srv).
-compile('PI OTP GenServer /w Persistence').
-compile(export_all).
-include("streams.hrl").
name(App) ->
list_to_atom(lists:concat([otp,App])).
emulate_otp(Parent,App) ->
catch unregister(name(App)),
catch register(name(App),self()),
process_flag(trap_exit, true),
put('$ancestors', [Parent]),
put('$initial_call', {application_controller, start, 1}).
% gen_server ctor
init(#gen_server{app=App,parent=Parent}=Server) ->
emulate_otp(Parent,App),
loop(Parent,{local,?MODULE}, Server, ?MODULE, infinity);
init({Parent, App, N, PredN, {Len,Msg}}) ->
emulate_otp(Parent,App),
T = erlang:monotonic_time(milli_seconds),
Server = #gen_server{file=otp:open(App),parent=Parent,app=App,
acc_pred=PredN,acc=N,acc_len=0,state=[],msg=Msg,
len=Len,circa= <<>>,time=T, init=T,sign= <<>>},
loop(Parent, {local, ?MODULE}, Server, ?MODULE, infinity).
% gen_server bootstrap
loop(Parent, Name, State, Mod, hibernate) -> erlang:hibernate(?MODULE,hibernate,[Parent, Name, State, Mod]);
loop(Parent, Name, State, Mod, Time) -> server(drain(Time), Parent, Name, State, Mod).
hibernate(Parent, Name, State, Mod) -> server(drain(), Parent, Name, State, Mod).
drain() -> receive Input -> Input end.
drain(Timeout) -> receive Input -> Input after Timeout -> {timeout,[],[]} end.
reply({To,Tag},Reply) -> To ! {Tag,Reply}.
% gen_server protocol
server({Fun, Sender, Msg}, P, N, S, M) ->
try dispatch(call(Fun,Msg,Sender,S),Sender,P,N,M)
catch Error:Reason ->
io:format("Exception: ~p",[{{Error,Reason},
erlang:get_stacktrace()}]) end;
server(Msg,P,N,S,M) ->
server({'$gen_cast', {self(),[]}, Msg}, P, N, S, M).
call(Fun,Msg,Sender,S) ->
case Fun of
'init' -> otp:'init'(Msg, Sender, S);
'EXIT' -> otp:'EXIT'(Msg, Sender, S);
'system' -> otp:'system' (Msg, Sender, S);
'timeout' -> otp:'timeout' (Msg, Sender, S);
'$gen_call' -> otp:'$gen_call'(Msg, Sender, S);
'$gen_cast' -> otp:'$gen_cast'(Msg, Sender, S) end.
dispatch(Call,Sender,P,N,M) ->
T = infinity,
case Call of
{stop,R,F} -> ok;
{stop,R,F,S} -> reply(F,R), R;
{ok,R,S} -> reply(Sender,R),
loop(P,N,S,M,T);
{ok,S} -> loop(P,N,S,M,T) end.
% server
server(Msg,Sender,#gen_server{acc=N}=Server) when N >= ?LIMIT ->
{stop, normal, Server};
server(Msg,Sender,#gen_server{acc=N,len=C,acc_len=AccLen}=Server) when AccLen > C ->
spawn(srv, init, [ otp:flush(Msg,Sender,Server#gen_server{acc=N+1}) ]),
{stop, normal, Server};
server(Msg,Sender,#gen_server{acc=N,circa=X,acc_len=AccLen,sign=Sign}=Server) ->
{Y, Len, S} = otp:append(X,{Msg,Sender},Sign,N),
otp:gc(),
{ok, [], Server#gen_server{acc_len=AccLen+Len,acc=N+1,circa=Y,sign=S}}.