Advertisement
Guest User

server.erl

a guest
Mar 7th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 3.97 KB | None | 0 0
  1. -module(server).
  2. -export([handle/2, initial_state/1, assign_tasks/2]).
  3. -include_lib("./defs.hrl").
  4.  
  5. %% inititial_state/2 and handle/2 are used togetger with the genserver module,
  6. %% explained in the lecture about Generic server.
  7.  
  8. % Produce initial state
  9. initial_state(ServerName) ->
  10.     #server_st{ name = ServerName, clients = [], channels = [] }.
  11.  
  12.  
  13. send_message(Pid, Msg) ->
  14.     spawn(server, fun(p, m) -> genserver:request(p, m) end, [Pid, Msg]).
  15.  
  16. %% ---------------------------------------------------------------------------
  17.  
  18. %% handle/2 handles requests from clients
  19.  
  20. %% All requests are processed by handle/2 receiving the request data (and the
  21. %% current state), performing the needed actions, and returning a tuple
  22. %% {reply, Reply, NewState}, where Reply is the reply to be sent to the client
  23. %% and NewState is the new state of the server.
  24.  
  25. %% Connect (and nick is available)
  26. handle_connect(St, ClientPID, Nick, false) ->
  27.     io:fwrite("Member joined with nick: ~p~n", [Nick]),
  28.     NewClients = St#server_st.clients ++ [#client_entry{ pid = ClientPID, nick = Nick }],
  29.     {reply, ok, St#server_st{ clients = NewClients }};
  30.  
  31. %% Connect (but nick is not available)
  32. handle_connect(St, _ClientPID, _Nick, _Client) ->
  33.     {reply, {error, nick_taken, "Nickname not available"}, St}.
  34.  
  35. %% Disconnect (but not connected)
  36. handle_disconnect(St, false) ->
  37.     {reply, {error, user_not_connected, "Not connected"}, St};
  38.  
  39. %% Disconnect
  40. handle_disconnect(St, Client) ->
  41.     {reply, ok, St#server_st{ clients = lists:delete(Client, St#server_st.clients) }}.
  42.  
  43. %% Join (channel exists)
  44. handle_join(St, ClientPID, ChannelAtom, _ChannelName, true) ->
  45.     Client = lists:keyfind(ClientPID, #client_entry.pid, St#server_st.clients),
  46.     Response = genserver:request(ChannelAtom, { join, Client#client_entry.pid, Client#client_entry.nick }),
  47.     { reply, Response, St };
  48.  
  49. %% Join (channel does not exist)
  50. handle_join(St, ClientPID, ChannelAtom, ChannelName, false) ->
  51.     genserver:start(ChannelAtom, channel:initial_state(ChannelName), fun channel:handle/2),
  52.     NewChannels = St#server_st.channels ++ [ChannelAtom],
  53.     NewSt = St#server_st{ channels = NewChannels },
  54.     handle_join(NewSt, ClientPID, ChannelAtom, ChannelName, true).
  55.  
  56. handle(St, {connect, ClientPID, Nick}) ->
  57.     handle_connect(St, ClientPID, Nick, lists:keyfind(Nick, #client_entry.nick, St#server_st.clients));
  58.  
  59. handle(St, {disconnect, ClientPID}) ->
  60.     handle_disconnect(St, lists:keyfind(ClientPID, #client_entry.pid, St#server_st.clients));
  61.  
  62. handle(St, {join, ClientPID, ChannelName }) ->
  63.     ChannelAtomName = re:replace(ChannelName, "#", "channel_", [global, {return, list}]),
  64.     ChannelAtom = list_to_atom(ChannelAtomName),
  65.     handle_join(St, ClientPID, ChannelAtom, ChannelName, lists:member(ChannelAtom, St#server_st.channels));
  66.  
  67. %% Handle task result
  68. handle(St, {task_result, ClientPID, Result}) ->
  69.      io:fwrite("Task finished by ~p with result: ~p~n", [ClientPID, Result]),
  70.      {reply, ok, St};
  71.  
  72. %% Handle task assignment
  73. handle(St, { assign_tasks, DestinationPid, F, Inputs}) ->
  74.     %% Retrieve list of all connected clients
  75.     %% TODO: This is not working... not sure why. :(
  76.     Clients = [ pid || {pid, _} <- St#server_st.clients ],
  77.     io:fwrite("Clients: ~p~n", [Clients]),
  78.     %%This seems to be working though!
  79.     Tasks = [ fun ()->F(Input) end || Input <- Inputs ],
  80.     io:fwrite("Tasks: ~p~n", [Tasks]),
  81.     ClientTasks = assign_tasks(Clients, Tasks),
  82.     %% Send a message to the client containing the task it has been assigned.
  83.     lists:map(fun ({Client, Task}) -> send_message(Client, {incoming_task, DestinationPid, Task}) end, ClientTasks),
  84.     io:fwrite("ClientTasks: ~p~n", [ClientTasks]),
  85.     {reply, ClientTasks, St}.
  86.  
  87. %% assign_tasks implemented as suggested by the lab description
  88.  
  89. assign_tasks([], _) -> [] ;
  90.  
  91. assign_tasks(Clients, Tasks) ->
  92.   [  {lists:nth(((N-1) rem length(Clients)) + 1, Clients), Task}
  93.   || {N,Task} <- lists:zip(lists:seq(1,length(Tasks)), Tasks) ].
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement