Packages
nitro
7.4.1
11.4.16
11.4.15
11.4.14
9.9.7
9.9.6
8.2.4
8.2.3
8.2.2
8.2.1
8.2.0
7.12.1
7.10.0
7.9.3
7.9.2
7.9.1
7.9.0
7.8.3
7.8.2
7.8.0
7.7.1
7.7.0
7.6.2
7.6.1
7.6.0
7.5.0
7.4.2
7.4.1
7.4.0
7.2.1
7.2.0
7.1.1
7.1.0
6.12.0
6.11.11
6.11.10
6.11.9
6.11.8
6.11.7
6.11.6
6.11.4
6.11.2
6.11.1
6.10.9
6.10.8
6.10.7
6.10.6
6.10.5
6.10.4
6.10.3
6.10.2
6.10.1
6.9.1
6.6.1
6.5.0
6.4.4
6.4.3
6.4.2
6.4.1
6.4.0
5.12.4
5.12.3
5.12.2
5.12.1
5.12.0
5.11.1
5.11.0
5.9.2
5.9.1
5.8.5
5.8.4
5.8.3
5.8.1
5.8.0
5.6.1
5.5.1
5.4.3
5.4.2
5.4.1
5.3.1
5.3.0
5.2.1
5.1.7
5.1.6
5.1.5
5.1.4
5.1.3
5.1.2
5.1.1
4.12.11
4.12.10
4.12.9
4.12.8
4.12.7
4.12.6
4.12.5
4.12.4
4.12.3
4.12.2
4.12.1
4.12.0
4.11.13
4.11.12
4.11.11
4.11.10
4.11.9
4.11.8
4.11.7
4.11.6
4.11.5
4.11.4
4.11.3
4.11.2
4.11.1
4.11.0
4.10.9
4.10.8
4.10.7
4.10.6
4.10.5
4.10.4
4.10.3
4.10.2
4.10.1
4.10.0
4.7.7
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.4.1
4.4.0
1.4.0
NITRO Nitrogen Web Framework
Current section
Files
Jump to
Current section
Files
src/nitro_pi.erl
-module(nitro_pi).
-description('NITRO Process Instance'). % gen_server replacement
-include_lib("nitro/include/nitro_pi.hrl").
-include_lib("nitro/include/n2o.hrl").
-behaviour(gen_server).
-export([start_link/1]).
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-export([start/1,stop/2,send/2,send/3,cast/2,cast/3,pid/2,restart/2,uid/2,cache/4,cache/3]).
start(#pi{table=Tab,name=Name,module=Module,sup=Sup,timeout=Timeout,restart=Restart} = Async) ->
ChildSpec = {{Tab,Name},{?MODULE,start_link,[Async]},Restart,Timeout,worker,[Module]},
case supervisor:start_child(Sup,ChildSpec) of
{ok,Pid} -> {Pid,Async#pi.name};
{ok,Pid,_} -> {Pid,Async#pi.name};
{error,Reason} -> {error,Reason} end.
stop(Tab,Name) ->
case nitro_pi:pid(Tab,Name) of
Pid when is_pid(Pid) ->
#pi{sup=Sup} = Async = send(Pid,{get}),
[ supervisor:F(Sup,{Tab,Name})
|| F <- [ terminate_child , delete_child ] ],
cache(Tab,{Tab,Name},undefined),
Async;
Data -> {error,{not_pid,Data}} end.
send(Pid,Message) when is_pid(Pid) -> gen_server:call(Pid,Message).
send(Tab,Name,Message) -> gen_server:call(nitro_pi:pid(Tab,Name),Message).
cast(Pid,Message) when is_pid(Pid) -> gen_server:cast(Pid,Message).
cast(Tab,Name,Message) -> gen_server:cast(nitro_pi:pid(Tab,Name),Message).
cache(Tab, Key) ->
Res = ets:lookup(Tab,Key),
Val = case Res of [] -> []; [Value] -> Value; Values -> Values end,
case Val of [] -> [];
{_,{infinity,X}} -> X;
{_,{Expire,X}} -> case Expire < calendar:local_time() of
true -> ets:delete(Tab,Key), [];
false -> X end end.
cache(Tab, Key, undefined) -> ets:delete(Tab,Key);
cache(Tab, Key, Value) -> cache(Tab, Key, Value, infinity).
cache(Tab, Key, Value, Till) -> ets:insert(Tab,{Key,{Till,Value}}), Value.
uid(_,_) ->
case os:type() of
{win32,nt} -> {Mega,Sec,Micro} = erlang:timestamp(), integer_to_list((Mega*1000000+Sec)*1000000+Micro);
_ -> erlang:integer_to_list(element(2,hd(lists:reverse(erlang:system_info(os_monotonic_time_source)))))
end.
pid(Tab,Name) -> cache(Tab,{Tab,Name}).
restart(Tab,Name) ->
case stop(Tab,Name) of
#pi{}=Async -> start(Async);
Error -> Error end.
handle(Mod,Message,Async) ->
case Mod:proc(Message,Async) of
{ok,S} -> {ok,S};
{ok,S,T} -> {ok,S,T};
{stop,X,Y,S} -> {stop,X,Y,S};
{stop,X,S} -> {stop,X,S};
{stop,S} -> {stop,S};
{reply,X,S,T} -> {reply,X,S,T};
{reply,X,S} -> {reply,X,S};
{noreply,X,S} -> {noreply,X,S};
{noreply,S} -> {noreply,S};
{_,S} -> {noreply,S};
S -> {noreply,S} end.
start_link (Parameters) -> gen_server:start_link(?MODULE, Parameters, []).
code_change(_,State,_) -> {ok, State}.
handle_call({get},_,Async) -> {reply,Async,Async};
handle_call(_,_,#pi{module=undefined}) -> {noreply,[]};
handle_call(Message,_,#pi{module=Mod}=Async) -> handle(Mod,Message,Async).
handle_cast(_, #pi{module=undefined}) -> {noreply,[]};
handle_cast(Message, #pi{module=Mod}=Async) -> handle(Mod,Message,Async).
handle_info(timeout, #pi{module=undefined}) -> {noreply,[]};
handle_info(timeout, #pi{module=Mod}=Async) -> handle(Mod,timeout,Async);
handle_info(_, #pi{module=undefined}) -> {noreply,[]};
handle_info(Message, #pi{module=Mod}=Async) -> handle(Mod,Message,Async);
handle_info(_, _) -> {noreply,[]}.
init(#pi{module=Mod,table=Tab,name=Name}=Handler) ->
cache(Tab,{Tab,Name},self(),infinity),
Mod:proc(init,Handler).
terminate(_Reason, #pi{name=Name,sup=Sup,table=Tab}) ->
spawn(fun() -> supervisor:delete_child(Sup,{Tab,Name}) end),
catch cache(Tab,{Tab,Name},undefined), ok.