aboutsummaryrefslogtreecommitdiffstats
path: root/common/server.erl
blob: bb64997ee16f717d77fc6bff599a284039a06098 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
%%  Inspired by  "Programming Erlang",
%%  published by The Pragmatic Bookshelf.
%%  Copyrights apply to this code.
%%  We make no guarantees that this code is fit for any purpose.
%%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.

-module(server).
-export([start/2, start/3, start_on_node/3, rpc/2, send/2, registration/2]).

start(Name, Mod) ->
    register(Name, spawn(fun() -> loop(Name, Mod, Mod:init()) end)).

start(Name, Mod, State) ->
    register(Name, spawn(fun() -> loop(Name, Mod, State) end)).

start_on_node(Node, Mod, State) ->
    Ref = make_ref(),
    Pid = spawn(Node, fun() -> loop(Ref, Mod, State) end),
    {Pid, Ref}.

send({Client, _}, Data) ->
    send(Client, Data);
send(Client, Data) ->
    Client ! Data.

wait_response({_, Name}) ->
    wait_response(Name);
wait_response(Name) ->
    receive
        {Name, crash} -> exit(rpc);
        {Name, ok, Response} -> Response
    end.

rpc(Client, Request) ->
    send(Client, {self(), Request}),
    wait_response(Client).

registration(Client, NewName) ->
    send(Client, {register, NewName}).

loop(Name, Mod, OldState) ->
    receive
	{register, NewName} ->
	    register(NewName, self()),
	    loop(NewName, Mod, OldState);

        {From, Request} ->
            try Mod:handle(Request, OldState) of
                {Response, NewState} ->
                    From ! {Name, ok, Response},
                    loop(Name, Mod, NewState)
            catch
                _: Why ->
                    log_the_error(Name, Request, Why),
                    From ! {Name, crash},
                    loop(Name, Mod, OldState)
            end;

	{'EXIT', From, Why} ->
            try Mod:handle({'EXIT', From, Why}, OldState) of
                NewState ->
		    loop(Name, Mod, NewState)
            catch
                _: Why ->
                    log_the_error(From, 'EXIT', Why),
                    loop(Name, Mod, OldState)
            end
    end.

log_the_error(Name, Request, Why) ->
    io:format("Server ~p request ~p ~n"
              "caused exception ~p~n",
              [Name, Request, Why]).