-module(balancer). -export([start/0, loop/1, allocate/0, deallocate/1]). -export([track/2]). start() -> register(balancer, spawn(balancer, loop, [server_one])), init(). init() -> try register(server_one, spawn(frequency, init, [[10,11,12,13,14,15]])) of _ -> ok catch error:badarg -> io:format("server_one already registered") end, try register(server_two, spawn(frequency, init, [[20,21,22,23,24,25]])) of _ -> ok catch error:badarg -> io:format("server_two already registered") end. %% Functional interface %% Moved these here from the frequency module allocate() -> server_request(allocate). deallocate(Freq) -> server_request({deallocate, Freq}). server_request(Msg) -> balancer ! {request, self(), Msg}, receive {reply, Reply} -> Reply end. % Sends the request to given server. route(R, S) -> Server = whereis(S), case Server of undefined -> {error, server_down}; _ -> Server ! R end. loop(S) -> receive {request, _Pid, allocate}=R -> route(R, S), loop(next(S)); {request, _Pid, {deallocate, Freq}}=R -> case correct_server(Freq) of out_of_range -> bad_freq_request; Server -> Server ! R end, loop(next(S)) end. %% (Unused) keeps a track of pids with existing allocations %% and avoids re-allocating again. track({reply, {ok, Freq}=R}, A) -> IsAllocated = lists:keymember(Freq, 2, A), case IsAllocated of true -> {{error, already_allocated}, A}; false -> {R, [Freq|A]} end; track({reply, {error, _E}=R}, A) -> {R, A}. next(server_one) -> server_two; next(server_two) -> server_one. correct_server(Freq) when Freq>=10, Freq=<15 -> server_one; correct_server(Freq) when Freq>=20, Freq=<25 -> server_two; correct_server(_Freq) -> out_of_range.