diff options
-rw-r--r-- | client/client.erl | 85 | ||||
-rw-r--r-- | common/server.erl | 64 | ||||
-rw-r--r-- | server/client.erl | 25 | ||||
-rw-r--r-- | server/dispatcher.erl | 18 |
4 files changed, 109 insertions, 83 deletions
diff --git a/client/client.erl b/client/client.erl index f8d5de2..d0bae4c 100644 --- a/client/client.erl +++ b/client/client.erl @@ -1,5 +1,19 @@ -module(client). --export([register/3, login/3, list/0, handle/3]). +-export([register/3, login/3, list/0, handle/2]). + +contains([], _) -> + false; +contains([H|_], H) -> + true; +contains([_|T], Search) -> + contains(T, Search). + +checkLogin(Value) -> + checkLogin(Value, contains(registered(), cli)). +checkLogin(Value, Value) -> + true; +checkLogin(_, _) -> + throw({error, login_state}). buildNode(Server) -> list_to_atom("distributed_music_system_main_node@" ++ Server). @@ -13,24 +27,21 @@ register(Server, Name, Password) -> {_, ok, Msg} -> Msg; {_, error, Msg} -> - Msg + {error, Msg} end. login(Server, Name, Password) -> + code:purge(server), + code:load_abs("../common/server"), + try checkLogin(false) of _ -> - rpc(Server, login, [self(), {Name, Password}]), + rpc(Server, login, [self(), {node(), Name, Password}]), receive - {_, ok, {ok, {logged_in, Client}}} -> - code:purge(server), - code:load_abs("../common/server"), - case server:start(cli, client, Client) of - true -> - {ok, logged_in}; - _ -> - {error, unable_to_login} - end; - {_, error, Msg} -> + {_, ok, {ok, {logged_in, {Pid, _}}}} -> + server:registration(Pid, cli), + {ok, logged_in}; + {_, _, Msg} -> Msg; Msg -> Msg @@ -40,52 +51,26 @@ login(Server, Name, Password) -> {error, logged_in} end. -contains([], _) -> - false; -contains([H|_], H) -> - true; -contains([_|T], Search) -> - contains(T, Search). - -checkLogin(Value) -> - checkLogin(Value, contains(registered(), cli)). -checkLogin(Value, Value) -> - true; -checkLogin(_, _) -> - throw({error, login_state}). - list() -> try checkLogin(true) of _ -> - cli ! {self(), list}, - receive - {_, ok, Msg} -> - Msg; - {_, error, Msg} -> - {error, Msg}; - Msg -> - {error, Msg} - end + server:rpc(cli, list) catch {error, login_state} -> {error, not_logged_in} end. -handle(Cli, list, Client) -> - Client ! {list}, +handle(list, Server) -> + Server ! list, receive - {_, {ok, List}} -> - io:format("List: ~w~n", List), - {{ok}, Client} + {ok, Msg} -> + {Msg, Server}; + Msg -> + {Msg, Server} end; -handle(Cli, {test, X}, Client) -> - Client ! {X}, - receive - Msg -> - io:format("Test: ~w~n~n", [Msg]), - {{ok}, Client} - end; +handle({change_state, NewState}, _) -> + {{ok}, NewState}; -handle(_, Cmd, Client) -> - {{error, {unknown_command, Cmd}}, Client}. +handle(Cmd, Server) -> + {{error, {unknown_command, Cmd}}, Server}. diff --git a/common/server.erl b/common/server.erl index 06922cc..bb64997 100644 --- a/common/server.erl +++ b/common/server.erl @@ -5,7 +5,7 @@ %% Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information. -module(server). --export([start/2, start/3, rpc/2, swap_code/2]). +-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)). @@ -13,34 +13,58 @@ start(Name, Mod) -> start(Name, Mod, State) -> register(Name, spawn(fun() -> loop(Name, Mod, State) end)). -swap_code(Name, Mod) -> rpc(Name, {swap_code, Mod}). +start_on_node(Node, Mod, State) -> + Ref = make_ref(), + Pid = spawn(Node, fun() -> loop(Ref, Mod, State) end), + {Pid, Ref}. -rpc(Name, Request) -> - Name ! {self(), Request}, +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 - {From, {swap_code, NewCallbackMod}} -> - From ! {Name, ok, ack}, - loop(Name, NewCallbackMod, OldState); + {register, NewName} -> + register(NewName, self()), + loop(NewName, Mod, OldState); + {From, Request} -> - {Response, NewState} = Mod:handle(From, Request, OldState), - From ! {Name, ok, Response}, - loop(Name, Mod, NewState) - %% try Mod:handle(From, 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 + 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) -> diff --git a/server/client.erl b/server/client.erl index 9d778f0..31d382f 100644 --- a/server/client.erl +++ b/server/client.erl @@ -1,23 +1,32 @@ -module(client). -export([start/1, loop/1, register/2, login/2]). -start(Client) -> +start(Node) -> process_flag(trap_exit, true), - spawn(client, loop, [Client]). + {Client, Ref} = server:start_on_node(Node, client, undef), + link(Client), + Server = spawn_link(client, loop, [{Client, Ref}]), + + case server:rpc({Client, Ref}, {change_state, Server}) of + {ok} -> + {ok, {Client, Ref}}; + _ -> + {error, unknown_error} + end. loop(Client) -> receive - {list} -> - Client ! {ok, foo}, + list -> + server:send(Client, {ok, {foo}}), loop(Client); - true -> - Client ! {error, unknown_command}, + Cmd -> + server:send(Client, {error, {unknown_command, Cmd}}), loop(Client) end. register(Client, {Name, Password}) -> dis ! {Client, {register, {Name, Password}}}. -login(Client, {Name, Password}) -> - dis ! {Client, {login, {Name, Password}}}. +login(Client, {Node, Name, Password}) -> + dis ! {Client, {login, {Node, Name, Password}}}. diff --git a/server/dispatcher.erl b/server/dispatcher.erl index 390f9e5..4f1f58b 100644 --- a/server/dispatcher.erl +++ b/server/dispatcher.erl @@ -1,5 +1,5 @@ -module(dispatcher). --export([start/0, init/0, handle/3]). +-export([start/0, init/0, handle/2]). start() -> code:purge(server), @@ -17,7 +17,7 @@ start() -> init() -> dict:new(). -handle(_, {register, {User, Password}}, Dict) -> +handle({register, {User, Password}}, Dict) -> case dict:find(User, Dict) of {ok, _}-> {{error, duplicated_user}, Dict}; @@ -26,13 +26,21 @@ handle(_, {register, {User, Password}}, Dict) -> {{ok, user_created}, dict:store(User, Password, Dict)} end; -handle(From, {login, {User, Password}}, Dict) -> +handle({login, {Node, User, Password}}, Dict) -> case dict:find(User, Dict) of {ok, Password} -> - {{ok, {logged_in, client:start(From)}}, Dict}; + case client:start(Node) of + {ok, Pid} -> + {{ok, {logged_in, Pid}}, Dict}; + _ -> + {{error, unable_to_login}, Dict} + end; _ -> {{error, user_or_password_invalid}, Dict} end; -handle(_, _, Dict) -> +handle({'EXIT', _, _}, Dict) -> + Dict; + +handle(_, Dict) -> {{error, unknown_command}, Dict}. |