Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -module(server).
- -export([handle/2, initial_state/1, assign_tasks/2]).
- -include_lib("./defs.hrl").
- %% inititial_state/2 and handle/2 are used togetger with the genserver module,
- %% explained in the lecture about Generic server.
- % Produce initial state
- initial_state(ServerName) ->
- #server_st{ name = ServerName, clients = [], channels = [] }.
- send_message(Pid, Msg) ->
- spawn(server, fun(p, m) -> genserver:request(p, m) end, [Pid, Msg]).
- %% ---------------------------------------------------------------------------
- %% handle/2 handles requests from clients
- %% All requests are processed by handle/2 receiving the request data (and the
- %% current state), performing the needed actions, and returning a tuple
- %% {reply, Reply, NewState}, where Reply is the reply to be sent to the client
- %% and NewState is the new state of the server.
- %% Connect (and nick is available)
- handle_connect(St, ClientPID, Nick, false) ->
- io:fwrite("Member joined with nick: ~p~n", [Nick]),
- NewClients = St#server_st.clients ++ [#client_entry{ pid = ClientPID, nick = Nick }],
- {reply, ok, St#server_st{ clients = NewClients }};
- %% Connect (but nick is not available)
- handle_connect(St, _ClientPID, _Nick, _Client) ->
- {reply, {error, nick_taken, "Nickname not available"}, St}.
- %% Disconnect (but not connected)
- handle_disconnect(St, false) ->
- {reply, {error, user_not_connected, "Not connected"}, St};
- %% Disconnect
- handle_disconnect(St, Client) ->
- {reply, ok, St#server_st{ clients = lists:delete(Client, St#server_st.clients) }}.
- %% Join (channel exists)
- handle_join(St, ClientPID, ChannelAtom, _ChannelName, true) ->
- Client = lists:keyfind(ClientPID, #client_entry.pid, St#server_st.clients),
- Response = genserver:request(ChannelAtom, { join, Client#client_entry.pid, Client#client_entry.nick }),
- { reply, Response, St };
- %% Join (channel does not exist)
- handle_join(St, ClientPID, ChannelAtom, ChannelName, false) ->
- genserver:start(ChannelAtom, channel:initial_state(ChannelName), fun channel:handle/2),
- NewChannels = St#server_st.channels ++ [ChannelAtom],
- NewSt = St#server_st{ channels = NewChannels },
- handle_join(NewSt, ClientPID, ChannelAtom, ChannelName, true).
- handle(St, {connect, ClientPID, Nick}) ->
- handle_connect(St, ClientPID, Nick, lists:keyfind(Nick, #client_entry.nick, St#server_st.clients));
- handle(St, {disconnect, ClientPID}) ->
- handle_disconnect(St, lists:keyfind(ClientPID, #client_entry.pid, St#server_st.clients));
- handle(St, {join, ClientPID, ChannelName }) ->
- ChannelAtomName = re:replace(ChannelName, "#", "channel_", [global, {return, list}]),
- ChannelAtom = list_to_atom(ChannelAtomName),
- handle_join(St, ClientPID, ChannelAtom, ChannelName, lists:member(ChannelAtom, St#server_st.channels));
- %% Handle task result
- handle(St, {task_result, ClientPID, Result}) ->
- io:fwrite("Task finished by ~p with result: ~p~n", [ClientPID, Result]),
- {reply, ok, St};
- %% Handle task assignment
- handle(St, { assign_tasks, DestinationPid, F, Inputs}) ->
- %% Retrieve list of all connected clients
- %% TODO: This is not working... not sure why. :(
- Clients = [ pid || {pid, _} <- St#server_st.clients ],
- io:fwrite("Clients: ~p~n", [Clients]),
- %%This seems to be working though!
- Tasks = [ fun ()->F(Input) end || Input <- Inputs ],
- io:fwrite("Tasks: ~p~n", [Tasks]),
- ClientTasks = assign_tasks(Clients, Tasks),
- %% Send a message to the client containing the task it has been assigned.
- lists:map(fun ({Client, Task}) -> send_message(Client, {incoming_task, DestinationPid, Task}) end, ClientTasks),
- io:fwrite("ClientTasks: ~p~n", [ClientTasks]),
- {reply, ClientTasks, St}.
- %% assign_tasks implemented as suggested by the lab description
- assign_tasks([], _) -> [] ;
- assign_tasks(Clients, Tasks) ->
- [ {lists:nth(((N-1) rem length(Clients)) + 1, Clients), Task}
- || {N,Task} <- lists:zip(lists:seq(1,length(Tasks)), Tasks) ].
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement