Skip to content

Commit

Permalink
otp-ify entire project
Browse files Browse the repository at this point in the history
  • Loading branch information
mojombo committed Oct 27, 2007
1 parent ec872a7 commit 2bd8d49
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
fuzed.conf
*.dump
5 changes: 5 additions & 0 deletions Rakefile
Expand Up @@ -51,4 +51,9 @@ end
desc "Upload site to Rubyforge"
task :site do
sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/fuzed"
end

task :fuzed do
# sh "erl -boot start_sasl +Bc +K true -smp enable -pz ./etest -pz ./ebin -pz ./ebin/eunit -name 'master@volcano.local' -run fuzed start"
sh %Q{yaws --conf fuzed.conf --pa './ebin' --name "master@volano.local" --runmod fuzed --erlarg '+Bc +K true -smp enabled'}
end
14 changes: 12 additions & 2 deletions bin/fuzed
Expand Up @@ -35,15 +35,25 @@ when 'start'
nodename = options[:name]

puts "Starting yaws server with name: #{nodename}"
system %Q{yaws --conf #{config} --pa #{Fuzed.relative 'elibs'} -name "#{nodename}" --runmod rails_connection_pool}
system %Q{yaws --conf #{config} --pa #{Fuzed.relative 'ebin'} \
-name "#{nodename}" --runmod fuzed \
--erlarg '+Bc +K true -smp enabled'}
when 'join'
nodename = options[:name]
master = options[:master_name]
rails = options[:rails]

puts "Starting a client named #{nodename} offering service to #{master}"
puts "Each node will run: 'fuzed-adapter #{rails}'"
system %Q{cd #{Fuzed.root}; erl -noshell -name #{nodename} -eval "join_cluster:start('#{master}','fuzed-adapter #{rails}')."}
cmd = %Q{cd #{Fuzed.root}; erl -boot start_sasl \
+Bc +K true -smp enabled \
-name "#{nodename}" \
-pa #{Fuzed.relative 'ebin'} \
-fuzed_node master "'#{master}'" \
-fuzed_node command '"#{Fuzed.root}/bin/fuzed-adapter #{rails}"' \
-run fuzed_node start}.squeeze(' ')
puts cmd
system(cmd)
else
puts 'Invalid command'
end
Expand Down
7 changes: 7 additions & 0 deletions elibs/fuzed.erl
@@ -0,0 +1,7 @@
-module(fuzed).

-export([start/0]).

start() ->
application:load(fuzed),
application:start(fuzed).
9 changes: 9 additions & 0 deletions elibs/fuzed_app.erl
@@ -0,0 +1,9 @@
-module(fuzed_app).
-behaviour(application).
-export([start/2, stop/1]).

start(_Type, StartArgs) ->
fuzed_sup:start_link(StartArgs).

stop(_State) ->
ok.
7 changes: 7 additions & 0 deletions elibs/fuzed_node.erl
@@ -0,0 +1,7 @@
-module(fuzed_node).

-export([start/0]).

start() ->
application:load(fuzed_node),
application:start(fuzed_node).
9 changes: 9 additions & 0 deletions elibs/fuzed_node_app.erl
@@ -0,0 +1,9 @@
-module(fuzed_node_app).
-behaviour(application).
-export([start/2, stop/1]).

start(_Type, StartArgs) ->
fuzed_node_sup:start_link(StartArgs).

stop(_State) ->
ok.
67 changes: 67 additions & 0 deletions elibs/fuzed_node_sup.erl
@@ -0,0 +1,67 @@
%%%-------------------------------------------------------------------
%%% Author : Tom Preston-Werner
%%%-------------------------------------------------------------------
-module(fuzed_node_sup).
-behaviour(supervisor).
-export([start/0, start_shell/0, start_link/1, init/1]).


% Supervisor Functions

start() ->
spawn(fun() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = [])
end).

start_shell() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []),
unlink(Pid).

start_link(Args) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, Args).


init([]) ->
ping_master(application:get_env(master)),
init_helper(application:get_env(command), application:get_env(num_nodes)).


% Helper functions

sleep(Time) ->
receive
after Time ->
ok
end.

ping_master({ok, Node}) -> pong = net_adm:ping(Node), sleep(5000);
ping_master(_) -> noop.

init_helper({ok, Command}, {ok, NumNodes}) when integer(NumNodes) ->
error_logger:info_msg("Starting with command: ~p~n", [Command]),
error_logger:info_msg("Starting with ~p nodes~n", [NumNodes]),
start_rm(Command, NumNodes);
init_helper({ok, Command}, undefined) ->
error_logger:info_msg("Starting with command: ~p~n", [Command]),
error_logger:info_msg("Starting with default (2) nodes~n"),
start_rm(Command, 2).

start_rm(Command, NumNodes) ->
Maker = fun() ->
Responder = port_wrapper:wrap(Command),
rails_connection_pool:add({node(), Responder}),
Responder
end,
Killer = fun(Responder) ->
Responder ! shutdown,
rails_connection_pool:remove({node(), Responder})
end,

{ok, {{one_for_one, 3, 10},
[{resource_manager,
{resource_manager, start_link, [Maker, Killer, NumNodes]},
permanent,
10000,
worker,
[resource_manager]}
]}}.
35 changes: 35 additions & 0 deletions elibs/fuzed_sup.erl
@@ -0,0 +1,35 @@
%%%-------------------------------------------------------------------
%%% Author : Tom Preston-Werner
%%%-------------------------------------------------------------------
-module(fuzed_sup).
-behaviour(supervisor).

-export([start/0, start_shell/0, start_link/1, init/1]).

start() ->
spawn(fun() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = [])
end).

start_shell() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []),
unlink(Pid).

start_link(Args) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, Args).

init([]) ->
{ok, {{one_for_one, 3, 10},
[{rails_connection_pool,
{rails_connection_pool, start_link, []},
permanent,
10000,
worker,
[rails_connection_pool]},
{pool_sweeper,
{pool_sweeper, start_link, []},
permanent,
10000,
worker,
[pool_sweeper]}
]}}.
125 changes: 125 additions & 0 deletions elibs/pool_sweeper.erl
@@ -0,0 +1,125 @@
%%%-------------------------------------------------------------------
%%% Author : Tom Preston-Werner
%%%-------------------------------------------------------------------
-module(pool_sweeper).
-behaviour(gen_server).

%% API
-export([start_link/0, watch/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-record(state,
{
node_pids = dict:new()
}
).

%%====================================================================
%% API
%%====================================================================

watch(Pid) ->
gen_server:cast(?MODULE, {watch, Pid}).

%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
%%--------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

%%====================================================================
%% gen_server callbacks
%%====================================================================

%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
init([]) ->
io:format("~p starting~n", [?MODULE]),
{ok, #state{}}.

%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.

%%--------------------------------------------------------------------
%% Function: handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({watch, Pid}, State) ->
Node = node(Pid),
error_logger:info_msg("Now monitoring node ~p~n", [Node]),
#state{node_pids=NodePids} = State,

case dict:find(Node, NodePids) of
{ok, _Pids} ->
NodePidsNew = dict:append(Node, Pid, NodePids);
error ->
NodePidsNew = dict:store(Node, [Pid], NodePids),
monitor_node(Node, true)
end,

{noreply, State#state{node_pids=NodePidsNew}}.

%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({nodedown, Node}, State) ->
error_logger:warning_msg("Node ~p went away. Removing from pools.~n", [Node]),
#state{node_pids=NodePids} = State,
Pids = dict:fetch(Node, NodePids),

remove_pids_from_pool(Pids),

NodePidsNew = dict:erase(Node, NodePids),

{noreply, State#state{node_pids=NodePidsNew}}.

%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> void()
%% Description: This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.

%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------

remove_pids_from_pool([]) ->
ok;
remove_pids_from_pool([Pid|Rest]) ->
rails_connection_pool:remove({node(Pid), Pid}),
remove_pids_from_pool(Rest).
10 changes: 7 additions & 3 deletions elibs/rails_connection_pool.erl
Expand Up @@ -82,7 +82,8 @@ list_all() ->
%% gen_server callbacks
%

init([Details]) ->
init([Details]) ->
io:format("~p starting~n", [?MODULE]),
{ok, #state{details=Details}}.

%%--------------------------------------------------------------------
Expand Down Expand Up @@ -130,13 +131,16 @@ handle_call({refund, Resource}, _Source, State) ->
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({remove, Rsrc}, State) ->
{noreply, State#state{ nodes=lists:remove(Rsrc, State#state.nodes),
active_nodes=lists:remove(Rsrc, State#state.active_nodes)}};
{noreply, State#state{ nodes=lists:delete(Rsrc, State#state.nodes),
active_nodes=lists:delete(Rsrc, State#state.active_nodes)}};
handle_cast({add, Rsrc}, State) ->
{Nodes, ActiveNodes} = {State#state.nodes, State#state.active_nodes},
ToAdd = not lists:member(Rsrc, Nodes),
if
ToAdd ->
error_logger:info_msg("Adding resource: ~p~n", [Rsrc]),
{_RNode, RPid} = Rsrc,
pool_sweeper:watch(RPid),
{noreply, State#state{nodes=[Rsrc|Nodes], active_nodes=[Rsrc|ActiveNodes]}};
true ->
{noreply, State}
Expand Down
5 changes: 5 additions & 0 deletions gems/.gitignore
@@ -0,0 +1,5 @@
*.beam
Makefile
*.o
*.bundle
pkg

0 comments on commit 2bd8d49

Please sign in to comment.