Advertisement
Guest User

Untitled

a guest
Nov 21st, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 5.68 KB | None | 0 0
  1. %% Event server
  2. -module(evserv).
  3. -compile(export_all).
  4.  
  5. -record(state, {events,    %% list of #event{} records
  6.                 clients}). %% list of Pids
  7.  
  8. -record(event, {name="",
  9.                 description="",
  10.                 pid,
  11.                 clientpid,
  12.                 timeout={{1970,1,1},{0,0,0}}}).
  13.  
  14. %%% User Interface
  15.  
  16. start() ->
  17.     register(?MODULE, Pid=spawn(?MODULE, init, [])),
  18.     Pid.
  19.  
  20. start_link() ->
  21.     register(?MODULE, Pid=spawn_link(?MODULE, init, [])),
  22.     Pid.
  23.  
  24. terminate() ->
  25.     ?MODULE ! shutdown.
  26.  
  27. init() ->
  28.     %% Loading events from a static file could be done here.
  29.     %% You would need to pass an argument to init (maybe change the functions
  30.     %% start/0 and start_link/0 to start/1 and start_link/1) telling where the
  31.     %% resource to find the events is. Then load it from here.
  32.     %% Another option is to just pass the event straight to the server
  33.     %% through this function.
  34.     loop(#state{events=orddict:new(),
  35.                 clients=orddict:new()}).
  36.  
  37. subscribe(Pid) ->
  38.     Ref = erlang:monitor(process, whereis(?MODULE)),
  39.     ?MODULE ! {self(), Ref, {subscribe, Pid}},
  40.     receive
  41.         {Ref, ok} ->
  42.             {ok, Ref};
  43.         {'DOWN', Ref, process, _Pid, Reason} ->
  44.             {error, Reason}
  45.     after 5000 ->
  46.         {error, timeout}
  47.     end.
  48.  
  49. add_event(Name, Description, TimeOut, Pid) ->
  50.     Ref = make_ref(),
  51.     ?MODULE ! {self(), Ref, {add, Name, Description, TimeOut, Pid}},
  52.     receive
  53.         {Ref, Msg} -> Msg
  54.     after 5000 ->
  55.         {error, timeout}
  56.     end.
  57.  
  58. add_event2(Name, Description, TimeOut) ->
  59.     Ref = make_ref(),
  60.     ?MODULE ! {self(), Ref, {add, Name, Description, TimeOut}},
  61.     receive
  62.         {Ref, {error, Reason}} -> erlang:error(Reason);
  63.         {Ref, Msg} -> Msg
  64.     after 5000 ->
  65.         {error, timeout}
  66.     end.
  67.  
  68. cancel(Name) ->
  69.     Ref = make_ref(),
  70.     ?MODULE ! {self(), Ref, {cancel, Name}},
  71.     receive
  72.         {Ref, ok} -> ok
  73.     after 5000 ->
  74.         {error, timeout}
  75.     end.
  76.  
  77. listen(Delay) ->
  78.     receive
  79.         M = {done, _Name, _Description} ->
  80.             [M | listen(0)]
  81.     after Delay*1000 ->
  82.         []
  83.     end.
  84.  
  85. %%% The Server itself
  86.  
  87. loop(S=#state{}) ->
  88.     receive
  89.         {Pid, MsgRef, {subscribe, Client}} ->
  90.             Ref = erlang:monitor(process, Client),
  91.             NewClients = orddict:store(Ref, Client, S#state.clients),
  92.             Pid ! {MsgRef, ok},
  93.             loop(S#state{clients=NewClients});
  94.         {Pid, MsgRef, {add, Name, Description, TimeOut, Pid}} ->
  95.             case valid_datetime(TimeOut) of
  96.                 true ->
  97.                     EventPid = event:start_link(Name, TimeOut),
  98.                     NewEvents = orddict:store(Name,
  99.                                               #event{name=Name,
  100.                                                      description=Description,
  101.                                                      pid=EventPid,
  102.                                                      clientpid=Pid,
  103.                                                      timeout=TimeOut
  104.                                                      },
  105.                                               S#state.events),
  106.                     Pid ! {MsgRef, ok},
  107.                     loop(S#state{events=NewEvents});
  108.                 false ->
  109.                     Pid ! {MsgRef, {error, bad_timeout}},
  110.                     loop(S)
  111.             end;
  112.         {Pid, MsgRef, {cancel, Name}} ->
  113.             Events = case orddict:find(Name, S#state.events) of
  114.                          {ok, E} ->
  115.                              event:cancel(E#event.pid),
  116.                              orddict:erase(Name, S#state.events);
  117.                          error ->
  118.                              S#state.events
  119.                      end,
  120.             Pid ! {MsgRef, ok},
  121.             loop(S#state{events=Events});
  122.         {done, Name} ->
  123.             case orddict:find(Name, S#state.events) of
  124.                 {ok, E} ->
  125.                     send_to_clients({done, E#event.name, E#event.description},
  126.                                     E#event.clientpid),
  127.                     NewEvents = orddict:erase(Name, S#state.events),
  128.                     loop(S#state{events=NewEvents});
  129.                 error ->
  130.                     %% This may happen if we cancel an event and
  131.                     %% it fires at the same time
  132.                     loop(S)
  133.             end;
  134.         shutdown ->
  135.             exit(shutdown);
  136.         {'DOWN', Ref, process, _Pid, _Reason} ->
  137.             loop(S#state{clients=orddict:erase(Ref, S#state.clients)});
  138.         code_change ->
  139.             ?MODULE:loop(S);
  140.         {Pid, debug} -> %% used as a hack to let me do some unit testing
  141.             Pid ! S,
  142.             loop(S);
  143.         Unknown ->
  144.             io:format("Unknown message: ~p~n",[Unknown]),
  145.             loop(S)
  146.     end.
  147.  
  148.  
  149. %%% Internal Functions
  150. send_to_clients(Msg, Pid) ->
  151.     Pid ! Msg.
  152.  
  153. valid_datetime({Date,Time}) ->
  154.     try
  155.         calendar:valid_date(Date) andalso valid_time(Time)
  156.     catch
  157.         error:function_clause -> %% not in {{Y,M,D},{H,Min,S}} format
  158.             false
  159.     end;
  160. valid_datetime(_) ->
  161.     false.
  162.  
  163. %% calendar has valid_date, but nothing for days.
  164. %% This function is based on its interface.
  165. %% Ugly, but ugh.
  166. valid_time({H,M,S}) -> valid_time(H,M,S).
  167.  
  168. valid_time(H,M,S) when H >= 0, H < 24,
  169.                        M >= 0, M < 60,
  170.                        S >= 0, S < 60 -> true;
  171. valid_time(_,_,_) -> false.
  172.  
  173.  
  174. przeslij(P) ->
  175.     receive
  176.         M = {done, _Name, _Description} ->
  177.             P![self(),M],przeslij(P) end.
  178.            
  179. klient(P, C)->subscribe(self()),
  180.             add_event("Alarm", "pobudka", C , self()),
  181.             przeslij(P).
  182.  
  183. klient2(P, C)->subscribe(self()),
  184.             add_event("Alarm - 2", "pobudka", C , self()),
  185.             przeslij(P).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement