aboutsummaryrefslogtreecommitdiff
path: root/erlbal_n.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erlbal_n.erl')
-rw-r--r--erlbal_n.erl91
1 files changed, 91 insertions, 0 deletions
diff --git a/erlbal_n.erl b/erlbal_n.erl
new file mode 100644
index 0000000..fba8621
--- /dev/null
+++ b/erlbal_n.erl
@@ -0,0 +1,91 @@
+-module(erlbal_n).
+-export([make_request/2, start_bal/0, stop_bal/1, start_server/5, stop_server/2, list_servers/1]).
+
+start_server(Balancer, Node, Fun, LoadFun, INITSTATE) when is_function(Fun, 2) andalso is_function(LoadFun, 0) andalso is_list(INITSTATE) ->
+ PID = spawn(Node, fun() -> server_loop(Fun, LoadFun, INITSTATE) end),
+ Balancer ! {add_node, PID}.
+
+stop_server(Balancer, PID) ->
+ Balancer ! {del_node, PID},
+ PID ! die.
+
+list_servers(Balancer) ->
+ Balancer ! {list_nodes, self()},
+ receive Nodes -> Nodes end.
+
+server_loop(Fun, LoadFun, STATE) ->
+ receive
+ {request, From, Serverlist, ARGS} ->
+ {Ret, NEWSTATE} = Fun(ARGS, STATE),
+ From ! Ret,
+ updatestates(Serverlist, self(), NEWSTATE),
+ server_loop(Fun, LoadFun, NEWSTATE);
+ {load, From} ->
+ From ! LoadFun(),
+ server_loop(Fun, LoadFun, STATE);
+ {update, NEWSTATE} ->
+ server_loop(Fun, LoadFun, NEWSTATE);
+ die ->
+ ok
+ end.
+
+updatestates([], _, _) ->
+ ok;
+updatestates([H|T], H, NEWSTATE) ->
+ updatestates(T, H, NEWSTATE);
+updatestates([H|T], P, NEWSTATE) ->
+ H ! {update, NEWSTATE},
+ updatestates(T, P, NEWSTATE).
+
+start_bal() ->
+ spawn(fun() -> bal_loop([]) end).
+
+stop_bal(Balancer) ->
+ Balancer ! die.
+
+bal_loop(Serverlist) ->
+ receive
+ {add_node, PID} ->
+ bal_loop(Serverlist ++ [PID]);
+ {del_node, PID} ->
+ bal_loop(Serverlist -- [PID]);
+ {list_nodes, From} ->
+ From ! Serverlist,
+ bal_loop(Serverlist);
+ {request, From, ARGS} ->
+ if
+ length(Serverlist) > 0 ->
+ PID = bal_worker(Serverlist),
+ PID ! {request, From, Serverlist, ARGS},
+ bal_loop(Serverlist);
+ true ->
+ bal_loop(Serverlist)
+ end;
+ die ->
+ ok
+ end.
+
+bal_worker([H|T]) ->
+ H ! {load, self()},
+ receive
+ N ->
+ bal_worker(T, N, H)
+ end.
+bal_worker([], _, PID) ->
+ PID;
+bal_worker([H|T], Best, PID) ->
+ H ! {load, self()},
+ receive
+ N ->
+ if
+ N > Best ->
+ bal_worker(T, N, H);
+ true ->
+ bal_worker(T, Best, PID)
+ end
+ end.
+
+
+make_request(Balancer, ARGS) when is_list(ARGS)->
+ Balancer ! {request, self(), ARGS},
+ receive Ret -> Ret end.