diff --git a/README b/README index d67dc32..776df31 100644 --- a/README +++ b/README @@ -2,14 +2,14 @@ fuzed by Dave Fayram , Tom Preston-Werner , Abhay Kumar - + Webiste: http://fuzed.rubyforge.org Mailing List: http://groups.google.com/group/fuzed == Summary Fuzed is an Erlang-based clustering system designed to let several -single-threaded processes (which may or may not be reliable) form +single-threaded processes (which may or may not be reliable) form into a pool which can serve requests to remote hosts. These resources need not be homogeneous, Fuzed breaks them up into homogeneous pools internally and serves out requests without "crossing the streams" @@ -24,7 +24,7 @@ to see exactly how it is used internally. * Erlang: http://www.erlang.org (>= 5.6.1) * Ruby: http://www.ruby-lang.org (>= 1.8.6) -* Ruby Gems: +* Ruby Gems: * rake: http://rake.rubyforge.org (>= 0.8.1) * rack: http://rack.rubyforge.org (>= 0.3.0) * erlectricity: http://github.com/mojombo/erlectricity (>= 0.2.1) diff --git a/Rakefile b/Rakefile index 3119eb4..766e530 100644 --- a/Rakefile +++ b/Rakefile @@ -37,7 +37,7 @@ task :test => [:default] do env_peek = ENV['MOD'] || ENV['MODS'] || ENV['MODULE'] || ENV['MODULES'] if env_peek mods = env_peek.split(",") - else + else mods = Dir["etest/*_test.erl"].map { |x| x.match(/etest\/(.*)_test.erl/)[1] } end mod_directives = mods.map {|m| "-run #{m} test"}.join(" ") diff --git a/conf/fuzed_base.config b/conf/fuzed_base.config index f7ba573..704b0ec 100644 --- a/conf/fuzed_base.config +++ b/conf/fuzed_base.config @@ -1,8 +1,8 @@ -%% rotating log and minimal tty -[{sasl, [ +%% rotating log and minimal tty +[{sasl, [ {sasl_error_logger, false}, {errlog_type, error}, - {error_logger_mf_dir,"/p/log/fuzed"}, - {error_logger_mf_maxbytes,52428800}, % 50 MB - {error_logger_mf_maxfiles, 10} -]}]. + {error_logger_mf_dir,"/p/log/fuzed"}, + {error_logger_mf_maxbytes,52428800}, % 50 MB + {error_logger_mf_maxfiles, 10} +]}]. diff --git a/elibs/fuzed_app.erl b/elibs/fuzed_app.erl index 1747361..ceeb54b 100644 --- a/elibs/fuzed_app.erl +++ b/elibs/fuzed_app.erl @@ -5,6 +5,6 @@ start(_Type, StartArgs) -> net_kernel:set_net_ticktime(30), fuzed_supervisor:start_link(StartArgs). - + stop(_State) -> ok. \ No newline at end of file diff --git a/elibs/fuzed_code_monitor.erl b/elibs/fuzed_code_monitor.erl index 4877517..2ecc746 100644 --- a/elibs/fuzed_code_monitor.erl +++ b/elibs/fuzed_code_monitor.erl @@ -1,13 +1,13 @@ %%%------------------------------------------------------------------- %%% File : /Users/dfayram/Projects/new_fuzed/elibs/fuzed_code_monitor.erl -%%% Author : +%%% Author : %%%------------------------------------------------------------------- -module(fuzed_code_monitor). -behaviour(gen_server). %% API -export([modified_modules/0, reload_modified_modules/0,reload_modified_modules_for_all_nodes/0, - reload_specified_modules/1, reload_ruby_code/0, reload_ruby_code_for_all_nodes/0, + reload_specified_modules/1, reload_ruby_code/0, reload_ruby_code_for_all_nodes/0, global_upgrade/1]). %% gen_server callbacks @@ -27,24 +27,24 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). - + %%==================================================================== %% gen_server callbacks & API %%==================================================================== -modified_modules() -> +modified_modules() -> gen_server:call(?MODULE, modified_modules). -reload_modified_modules() -> +reload_modified_modules() -> gen_server:cast(?MODULE, reset). -reload_specified_modules(Modules) -> +reload_specified_modules(Modules) -> spawn(fun() -> [force_reload_module(M) || M <- Modules] end), ok. - -reload_ruby_code() -> + +reload_ruby_code() -> spawn( - fun() -> + fun() -> try resource_manager:cycle() catch error:_ -> ok @@ -53,7 +53,7 @@ reload_ruby_code() -> ), ok. -reload_ruby_code_for_all_nodes() -> +reload_ruby_code_for_all_nodes() -> reload_ruby_code(), [rpc:call(Node, ?MODULE, reload_ruby_code, []) || Node <- nodes()], nodes(). @@ -68,7 +68,7 @@ global_upgrade(ruby) -> reload_ruby_code_for_all_nodes(); global_upgrade(erlang) -> reload_modified_modules_for_all_nodes(); global_upgrade(all) -> global_upgrade(erlang), global_upgrade(ruby); global_upgrade(_) -> global_upgrade(all). - + %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | @@ -89,7 +89,7 @@ init([]) -> %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- -handle_call(modified_modules, _From, State) -> +handle_call(modified_modules, _From, State) -> {reply, local_modified_modules(), State}; handle_call(_Request, _From, State) -> Reply = ok, @@ -101,8 +101,8 @@ handle_call(_Request, _From, State) -> %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- -handle_cast(reset, State) -> - spawn(fun() -> timer:sleep(1000), [force_reload_module(M) || M <- mm()] end), +handle_cast(reset, State) -> + spawn(fun() -> timer:sleep(1000), [force_reload_module(M) || M <- mm()] end), {noreply, State}; handle_cast(_Msg, State) -> {noreply, State}. @@ -183,6 +183,6 @@ find_module_file(Path) -> end end. -force_reload_module(Module) -> +force_reload_module(Module) -> code:purge(Module), code:load_file(Module). \ No newline at end of file diff --git a/elibs/fuzed_frontend_app.erl b/elibs/fuzed_frontend_app.erl index efb0f14..ae4b49f 100644 --- a/elibs/fuzed_frontend_app.erl +++ b/elibs/fuzed_frontend_app.erl @@ -5,6 +5,6 @@ start(_Type, StartArgs) -> net_kernel:set_net_ticktime(30), fuzed_frontend_supervisor:start_link(StartArgs). - + stop(_State) -> ok. diff --git a/elibs/fuzed_frontend_supervisor.erl b/elibs/fuzed_frontend_supervisor.erl index 86b477d..f353790 100644 --- a/elibs/fuzed_frontend_supervisor.erl +++ b/elibs/fuzed_frontend_supervisor.erl @@ -9,14 +9,14 @@ 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([]) -> case application:get_env(pidfile) of @@ -25,7 +25,7 @@ init([]) -> ok = file:write_file(Location, list_to_binary(Pid)); undefined -> ok end, - + Master = application:get_env(master), case Master of {ok, MasterNode} -> @@ -33,7 +33,7 @@ init([]) -> undefined -> MasterNode = node() end, - + case application:get_env(conf) of {ok, Conf} -> yaws_frontend:start(Conf); @@ -45,13 +45,13 @@ init([]) -> ResponderModule = figure_responder(), FrameworkModule = figure_framework_module(), AppModSpecs = process_appmods(application:get_env(appmods)), - + case application:get_env(http_server) of {ok, mochiweb} -> mochiweb_frontend:start(IP, Port, DocRoot, SSL, ResponderModule, FrameworkModule, AppModSpecs); _ -> yaws_frontend:start(IP, Port, DocRoot, SSL, ResponderModule, FrameworkModule, AppModSpecs) end end, - + {ok, {{one_for_one, 10, 600}, [{master_beater, {master_beater, start_link, [MasterNode, ?GLOBAL_TIMEOUT, ?SLEEP_CYCLE]}, @@ -75,15 +75,15 @@ ssl_config() -> {_Any2, undefined} -> none; _Else -> {ssl, Key, Cert} end. - + % Helper functions -ping_master(Node) -> +ping_master(Node) -> case net_adm:ping(Node) of - pong -> + pong -> timer:sleep(?SLEEP_CYCLE), ok; - pang -> + pang -> error_logger:info_msg("Master node ~p not available. Retrying in 5 seconds.~n", [Node]), timer:sleep(?SLEEP_CYCLE), ping_master(Node) @@ -95,12 +95,12 @@ figure_responder() -> Module; undefined -> frontend_responder end. - + figure_framework_module() -> {ok, Framework} = application:get_env(framework), FrameworkString = atom_to_list(Framework), FrameworkModuleString = FrameworkString ++ "_framework", list_to_atom(FrameworkModuleString). - + process_appmods(undefined) -> []; process_appmods({ok, V}) -> V. \ No newline at end of file diff --git a/elibs/fuzed_node_app.erl b/elibs/fuzed_node_app.erl index 7a2d65f..68980a1 100644 --- a/elibs/fuzed_node_app.erl +++ b/elibs/fuzed_node_app.erl @@ -5,6 +5,6 @@ start(_Type, StartArgs) -> net_kernel:set_net_ticktime(30), fuzed_node_supervisor:start_link(StartArgs). - + stop(_State) -> ok. \ No newline at end of file diff --git a/elibs/fuzed_node_supervisor.erl b/elibs/fuzed_node_supervisor.erl index 42afe56..3e588f9 100644 --- a/elibs/fuzed_node_supervisor.erl +++ b/elibs/fuzed_node_supervisor.erl @@ -9,14 +9,14 @@ 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([]) -> Master = application:get_env(master), @@ -29,35 +29,35 @@ init([]) -> {ok, NumNodes} = application:get_env(num_nodes), {ok, Spec} = application:get_env(spec), init_helper(MasterNode, NumNodes, Spec). - + % Helper functions -ping_master(Node) -> +ping_master(Node) -> case net_adm:ping(Node) of - pong -> + pong -> timer:sleep(?SLEEP_CYCLE), ok; - pang -> + pang -> error_logger:info_msg("Master node ~p not available. Retrying in 5 seconds.~n", [Node]), timer:sleep(?SLEEP_CYCLE), ping_master(Node) end. init_helper(Master, NumNodes, Spec) when is_integer(NumNodes) -> - error_logger:info_msg("Starting with ~p set(s) of nodes.~n", [NumNodes]), + error_logger:info_msg("Starting with ~p set(s) of nodes.~n", [NumNodes]), start_rm(Master, explode_spec(Spec, NumNodes)). - -explode_spec(Specs, N) -> + +explode_spec(Specs, N) -> SBins = [list_to_binary(X) || X <- Specs], lists:sort([binary_to_list(X) || X <- lists:flatten(lists:duplicate(N, SBins))]). start_rm(Master, NodeSpec) -> error_logger:info_msg("Starting with spec: ~p~n", [NodeSpec]), - Maker = fun(N) -> + Maker = fun(N) -> node_api:heat(N, ?HEAT_DURATION) end, - Killer = fun(X) -> X end, + Killer = fun(X) -> X end, {ok, {{one_for_one, 10, 600}, [{resource_manager, {resource_manager, start_link, [Master, NodeSpec, Maker, Killer, ?GLOBAL_TIMEOUT]}, diff --git a/elibs/fuzed_supervisor.erl b/elibs/fuzed_supervisor.erl index 9168f9b..5077ad4 100644 --- a/elibs/fuzed_supervisor.erl +++ b/elibs/fuzed_supervisor.erl @@ -11,28 +11,28 @@ 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) -> application:set_env(fuzed, in_rotation, true), supervisor:start_link({local, ?MODULE}, ?MODULE, Args). - + init([]) -> % start the master server IP = {0,0,0,0}, Port = 9001, DocRoot = filename:dirname(code:which(?MODULE)) ++ "/../web", - + case application:get_env(http_server) of {ok, mochiweb} -> mochiweb_master:start(IP, Port, DocRoot); _ -> yaws_master:start(IP, Port, DocRoot) end, - + %erl_boot_server:add_subnet({0, 0, 0, 0}, {0, 0, 0, 0}), - + % return the supervisor spec for the resource fountain {ok, {{one_for_one, 100, 300}, [{resource_fountain, @@ -44,7 +44,7 @@ init([]) -> {fuzed_code_monitor, {fuzed_code_monitor, start_link, []}, permanent, 10000, worker, [fuzed_code_monitor]}, - {logger, + {logger, {logger, start_link, ["/var/log/fuzed"]}, permanent, 10000, worker, [logger]} ]}}. diff --git a/elibs/logger.erl b/elibs/logger.erl index 789e82b..bbf57a7 100644 --- a/elibs/logger.erl +++ b/elibs/logger.erl @@ -21,7 +21,7 @@ } ). --record(state, +-record(state, { log_dir, details_selectors = [], @@ -35,33 +35,33 @@ enable_logging(Details) -> gen_server:call(?MODULE, {enable_logging, Details}). - + disable_logging(Details) -> gen_server:call(?MODULE, {disable_logging, Details}). - + list_details_selectors() -> gen_server:call(?MODULE, {list_details_selectors}). - + list_pools() -> gen_server:call(?MODULE, {list_pools}). - - + + is_pool_logging(Pool, Details) -> gen_server:call(?MODULE, {is_pool_logging, Pool, Details}). - - -pool_created(Pool) -> + + +pool_created(Pool) -> gen_server:cast(?MODULE, {pool_created, Pool}). - -pool_removed(Pool) -> + +pool_removed(Pool) -> gen_server:cast(?MODULE, {pool_removed, Pool}). - + node_joined(Pool, Node) -> gen_server:cast(?MODULE, {node_joined, Pool, Node}). - + node_left(Pool, Node) -> gen_server:cast(?MODULE, {node_left, Pool, Node}). - + %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server @@ -107,7 +107,7 @@ handle_call({enable_logging, Details}, _From, State) -> NewPoolsFinfos = init_finfos(Pools, State#state.pools_finfos, State#state.log_dir), {reply, ok, State#state{details_selectors=NewDetailsSelectors, pools_finfos=NewPoolsFinfos}} end; - + handle_call({disable_logging, Details}, _From, State) -> DetailsSelectors = State#state.details_selectors, IsMember = lists:member(Details, DetailsSelectors), @@ -120,13 +120,13 @@ handle_call({disable_logging, Details}, _From, State) -> error_logger:info_msg("No logging has been enabled for those details~n", []), {reply, ok, State} end; - + handle_call({list_details_selectors}, _From, State) -> {reply, State#state.details_selectors, State}; - + handle_call({list_pools}, _From, State) -> {reply, dict:fetch_keys(State#state.pools_finfos), State}; - + handle_call({is_pool_logging, Pool, Details}, _From, State) -> Pred = fun(Spec) -> Score = scoring:score_details(Spec, Details), @@ -144,7 +144,7 @@ handle_call({is_pool_logging, Pool, Details}, _From, State) -> NewPoolsFinfos = init_finfo(Pool, State#state.pools_finfos, State#state.log_dir, Details), {reply, true, State#state{pools_finfos=NewPoolsFinfos}} end; - + handle_call(Any, _From, State) -> error_logger:info_msg("Unexpected call: ~p~n", [Any]), {reply, ok, State}. @@ -159,22 +159,22 @@ handle_cast({pool_created, Pool}, State) -> Finfo = dict:fetch(Pool, State#state.pools_finfos), log_line(Finfo#finfo.log_file, "Pool created"), {noreply, State}; - + handle_cast({pool_removed, Pool}, State) -> Finfo = dict:fetch(Pool, State#state.pools_finfos), log_line(Finfo#finfo.log_file, "Pool removed"), {noreply, State}; - + handle_cast({node_joined, Pool, Node}, State) -> Finfo = dict:fetch(Pool, State#state.pools_finfos), log_line(Finfo#finfo.log_file, "Node joined: ~p ~p", [Node, node(Node)]), {noreply, State}; - + handle_cast({node_left, Pool, Node}, State) -> Finfo = dict:fetch(Pool, State#state.pools_finfos), log_line(Finfo#finfo.log_file, "Node left: ~p ~p", [Node, node(Node)]), {noreply, State}. - + %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | @@ -213,7 +213,7 @@ set_all_logging(Details, Logging) -> {MatchDetails, _Score} = Match, resource_fountain:pool_for_details(MatchDetails) end, - SetLoggingFun = fun(Pool) -> + SetLoggingFun = fun(Pool) -> case Logging of false -> error_logger:info_msg("Disabling logging for pool ~p~n", [Pool]); true -> error_logger:info_msg("Enabling logging for pool ~p~n", [Pool]) @@ -233,7 +233,7 @@ init_finfo(Pool, PoolsFinfos, LogDir, Details) -> Finfo = init_files(Hash, Details, LogDir), dict:store(Pool, Finfo, PoolsFinfos) end. - + init_finfos(Pools, PoolsFinfos, LogDir) -> InitFun = fun(Pool, Dict) -> Details = resource_pool:details(Pool), @@ -246,7 +246,7 @@ init_finfos(Pools, PoolsFinfos, LogDir) -> end end, lists:foldl(InitFun, PoolsFinfos, Pools). - + init_files(Hash, Details, LogDir) -> StringHash = erlang:integer_to_list(Hash), LogFile = filename:join(LogDir, StringHash ++ ".log"), @@ -260,10 +260,10 @@ init_files(Hash, Details, LogDir) -> error_logger:info_msg("Unable to create Logger NameFile ~p: ~p~n", [NameFile, Reason]) end, #finfo{log_file=LogFile, name_file=NameFile}. - + log_line(LogFile, Line) -> log_line(LogFile, Line, []). - + log_line(LogFile, Line, Data) -> case file:open(LogFile, [write, append]) of {ok, Fh} -> diff --git a/elibs/master_beater.erl b/elibs/master_beater.erl index 6650217..6bd95cb 100644 --- a/elibs/master_beater.erl +++ b/elibs/master_beater.erl @@ -20,7 +20,7 @@ start_link(Master, UpRetry, DownRetry) -> gen_fsm:start_link({local, ?MODULE}, ?MODULE, [Master, UpRetry, DownRetry], []). - + ping() -> gen_fsm:send_event(?MODULE, ping). @@ -45,8 +45,8 @@ up({ping, Ref}, StateData) when Ref =:= StateData#state.ping_ref -> end; up({ping, _Ref}, StateData) -> {next_state, up, StateData}. - - + + down({ping, Ref}, StateData) when Ref =:= StateData#state.ping_ref -> case check_master_connection(StateData#state.master) of ok -> @@ -59,8 +59,8 @@ down({ping, Ref}, StateData) when Ref =:= StateData#state.ping_ref -> end; down({ping, _Ref}, StateData) -> {next_state, down, StateData}. - - + + rejoin({ping, Ref}, StateData) when Ref =:= StateData#state.ping_ref -> case check_master_responsive() of ok -> @@ -78,7 +78,7 @@ rejoin({ping, _Ref}, StateData) -> {next_state, rejoin, StateData}. -handle_info({'EXIT', Pid, Reason}, _StateName, StateData) -> +handle_info({'EXIT', Pid, Reason}, _StateName, StateData) -> error_logger:warning_msg("Pid ~p went away because ~p .~n", [Pid, Reason]), Ref1 = pinger(500), {next_state, down, StateData#state{ping_ref = Ref1}}; @@ -88,23 +88,23 @@ handle_info({nodeup, _Node, _Reason}, StateName, StateData) -> handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. - - + + handle_sync_event(_Event, _From, StateName, StateData) -> {next_state, StateName, StateData}. - + %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %%-------------------------------------------------------------------- terminate(_Reason, _StateName, _StateData) -> ok. - + %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %%-------------------------------------------------------------------- code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. - + %%%%%%%%%%%%%%% pinger(Delay) -> @@ -116,13 +116,13 @@ check_master_connection(Node) -> case net_adm:ping(Node) of pong -> ok; - pang -> + pang -> fail end. - + check_master_responsive() -> try resource_fountain:identity() of - {ok, _Node} -> + {ok, _Node} -> ok; _ -> fail diff --git a/elibs/node_api.erl b/elibs/node_api.erl index aec0a2b..21f477c 100644 --- a/elibs/node_api.erl +++ b/elibs/node_api.erl @@ -13,22 +13,22 @@ independent_pool_call(Pool, Method, Parameters, RetType, Parent) -> Resource = resource_pool:get(Pool), - Result = - try + Result = + try case is_remote_process_alive(Resource) of true -> send_call(Resource, Method, RetType, Parameters); false -> parent_died end - after + after resource_pool:refund(Pool, Resource) end, Parent ! {self(), result, Result}, done. -safely_send_call_to_pool(Method, Parameters, ApiSpec, Details) -> +safely_send_call_to_pool(Method, Parameters, ApiSpec, Details) -> safely_send_call_to_pool(Method, Parameters, ApiSpec, pure, Details). -% Valid retkinds are json and erlang -safely_send_call_to_pool(Method, Parameters, ApiSpec, RetType, Details) -> +% Valid retkinds are json and erlang +safely_send_call_to_pool(Method, Parameters, ApiSpec, RetType, Details) -> PoolSearch = resource_fountain:pool_for_dispatch(ApiSpec, Details), safely_send_call_to_pool_no_lookup(Method, Parameters, RetType, PoolSearch). @@ -47,100 +47,100 @@ safely_send_call_to_pool_no_lookup(Method, Parameters, RetType, Pool) -> send_call(Port, Method, Parameters) -> send_call(Port, Method, pure, Parameters). -send_call(Port, Method, RetType, Parameters) -> - Call = [Method,RetType|prepare_parameters(Parameters)], +send_call(Port, Method, RetType, Parameters) -> + Call = [Method,RetType|prepare_parameters(Parameters)], case send_call_object_to_port(Port, Call) of {error, Error} -> {error, binary_to_list(Error)}; - {Port, timed_out} -> + {Port, timed_out} -> {error, "Node timeout!"}; % {result, Result} is expected, or {result {raw, Result}} - X -> + X -> X end. -send_call_object_to_port(Port, Call) -> +send_call_object_to_port(Port, Call) -> port_wrapper:send(Port, {call, Call}), receive {Port, Value} -> Value end. -parse_sentence(Port, Sentence) -> +parse_sentence(Port, Sentence) -> BSent = list_to_binary(Sentence), port_wrapper:send(Port, {parse, BSent}), receive {Port, {result, Fstruct}} -> Fstruct end. - -morphemes_for_sentence(Port, Sentence) -> + +morphemes_for_sentence(Port, Sentence) -> BSent = list_to_binary(Sentence), port_wrapper:send(Port, {morphemes_for_sentence, BSent}), receive {Port, {result, Morphs}} -> Morphs end. - -semrep_for_sentence(Port, Sentence) -> + +semrep_for_sentence(Port, Sentence) -> BSent = list_to_binary(Sentence), port_wrapper:send(Port, {parse, BSent}), receive {Port, {result, Semrep}} -> Semrep end. -nlmatch_semreps(Port, Semrep1, Semrep2) -> +nlmatch_semreps(Port, Semrep1, Semrep2) -> port_wrapper:send(Port, {nlmatch, Semrep1, Semrep2}), receive {Port, {result, Matchstring}} -> Matchstring end. - -details(Port) -> + +details(Port) -> port_wrapper:send(Port, config), - receive + receive {Port, {result, Details}} -> process_details(Details) end. -heat(Port) -> +heat(Port) -> Port ! {self(), heat}, receive {Port, hot} -> ok end. -heat(Port, Timeout) -> +heat(Port, Timeout) -> Port ! {self(), heat}, receive {Port, hot} -> ok after Timeout -> fail end. -api(Port) -> +api(Port) -> Port ! {self(), api}, receive {Port, API} -> API - after ?SLEEP_CYCLE -> + after ?SLEEP_CYCLE -> 0 end. api_signature(Port) -> erlang:phash2(api(Port)). -stop(Port) -> +stop(Port) -> Port ! shutdown, ok. -process_details(DTuple) -> +process_details(DTuple) -> Details = erlang:tuple_to_list(DTuple), Listifiers = [<<"tags">>, <<"roles">>], F = fun(Key, Intails) -> listify_detail_for_key(Key, Intails) end, lists:map(fun({K,V}) -> {K, purify_detail_value(V)} end, lists:foldl(F, Details, Listifiers)). -listify_detail_for_key(Key, Details) -> +listify_detail_for_key(Key, Details) -> case lists:keysearch(Key, 1, Details) of - {value, KeyTuple} -> + {value, KeyTuple} -> [Key|Rest] = erlang:tuple_to_list(KeyTuple), lists:keyreplace(Key, 1, Details, {Key, Rest}) ; - false -> + false -> [{Key, []}|Details] end. -prepare_parameters(L) when is_list(L) -> +prepare_parameters(L) when is_list(L) -> [{K,prepare_pvalue(V)} || {K,V} <- L]. atom_to_binary(Atom) when is_atom(Atom) -> list_to_binary(atom_to_list(Atom)). diff --git a/elibs/pool_sweeper.erl b/elibs/pool_sweeper.erl index 298e8fb..5401898 100644 --- a/elibs/pool_sweeper.erl +++ b/elibs/pool_sweeper.erl @@ -11,7 +11,7 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --record(state, +-record(state, { node_pids = dict:new(), pid_pools = dict:new() @@ -22,9 +22,9 @@ %% API %%==================================================================== -watch(Pool, Pid) -> +watch(Pool, Pid) -> gen_server:cast(?MODULE, {watch, Pool, Pid}). - + %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server @@ -71,16 +71,16 @@ handle_cast({watch, Pool, Pid}, State) -> Node = node(Pid), error_logger:info_msg("Now monitoring node ~p~n", [Node]), #state{node_pids=NodePids, pid_pools=PidPools} = State, - + PidPoolsNew = dict:store(Pid, Pool, PidPools), - + case dict:find(Node, NodePids) of {ok, _Pids} -> NodePidsNew = dict:append(Node, Pid, NodePids); error -> NodePidsNew = dict:store(Node, [Pid], NodePids) end, - + {noreply, State#state{node_pids=NodePidsNew, pid_pools=PidPoolsNew}}. %%-------------------------------------------------------------------- @@ -96,9 +96,9 @@ handle_info({nodedown, Node, Reason}, State) -> error_logger:warning_msg("Node ~p went away because ~p. Removing from pools.~n", [Node, Reason]), #state{node_pids=NodePids, pid_pools=PidPools} = State, case dict:find(Node, NodePids) of - error -> + error -> {noreply, State}; - {ok, Pids} -> + {ok, Pids} -> PidPoolsNew = remove_pids_from_pools(Pids, PidPools), NodePidsNew = dict:erase(Node, NodePids), sweep_pools_from_fountain(Pids, PidPools), @@ -131,7 +131,7 @@ remove_pids_from_pools([], PidPools) -> remove_pids_from_pools([Pid|Rest], PidPools) -> case dict:find(Pid, PidPools) of error -> remove_pids_from_pools(Rest, PidPools); - {ok, Pool} -> + {ok, Pool} -> resource_pool:remove(Pool, Pid), PidPoolsNew = dict:erase(Pid, PidPools), remove_pids_from_pools(Rest, PidPoolsNew) @@ -139,7 +139,7 @@ remove_pids_from_pools([Pid|Rest], PidPools) -> sweep_pools_from_fountain(Pids, PidPools) -> spff_helper([dict:fetch(X, PidPools) || X <- Pids], []). spff_helper([], _) -> ok; -spff_helper([Pool|Rest], AlreadyDone) -> +spff_helper([Pool|Rest], AlreadyDone) -> case lists:member(Pool, AlreadyDone) of false -> resource_fountain:remove_pool_if_empty(Pool), spff_helper(Rest, [Pool|AlreadyDone]); true -> spff_helper(Rest,AlreadyDone) diff --git a/elibs/port_wrapper.erl b/elibs/port_wrapper.erl index e5ec47c..ed1d7ff 100644 --- a/elibs/port_wrapper.erl +++ b/elibs/port_wrapper.erl @@ -4,31 +4,31 @@ wrap(Command) -> spawn(fun() -> process_flag(trap_exit, true), Port = create_port(Command), loop(Port, infinity, Command) end). -wrap(Command, Timeout) -> +wrap(Command, Timeout) -> spawn(fun() -> process_flag(trap_exit, true), Port = create_port(Command), loop(Port, Timeout, Command) end). - + wrap_link(Command) -> spawn_link(fun() -> process_flag(trap_exit, true), Port = create_port(Command), link(Port), loop(Port, infinity, Command) end). -wrap_link(Command, Timeout) -> +wrap_link(Command, Timeout) -> spawn_link(fun() -> process_flag(trap_exit, true), Port = create_port(Command), link(Port), loop(Port, Timeout, Command) end). -rpc(WrappedPort, Message) -> +rpc(WrappedPort, Message) -> send(WrappedPort, Message), receive {WrappedPort, Result} -> Result - after 15000 -> + after 15000 -> {WrappedPort, timed_out} end. - + send(WrappedPort, Message) -> WrappedPort ! {self(), {command, term_to_binary(Message)}}, WrappedPort. pure_send(WrappedPort, Message) -> WrappedPort ! {self(), {just_send_a_command, term_to_binary(Message)}}, - WrappedPort. + WrappedPort. -shutdown(WrappedPort) -> +shutdown(WrappedPort) -> WrappedPort ! shutdown, true. @@ -37,32 +37,32 @@ create_port(Command) -> loop(Port, Timeout, Command) -> receive - noose -> + noose -> port_close(Port), noose; shutdown -> port_close(Port), exit(shutdown); - {Source, host} -> + {Source, host} -> Source ! {Port, node()}, loop(Port,Timeout,Command); - {Source, heat} -> + {Source, heat} -> Port ! {self(), {command, term_to_binary(ping)}}, Hot = term_to_binary(pong), receive - {Port, {data, Hot}} -> + {Port, {data, Hot}} -> Source ! {self(), hot} end, loop(Port, Timeout, Command); - {Source, api} -> + {Source, api} -> Port ! {self(), {command, term_to_binary(api)}}, receive - {Port, {data, Result}} -> + {Port, {data, Result}} -> {result, Api} = binary_to_term(Result), Source ! {self(), tuple_to_list(Api)} end, loop(Port,Timeout,Command); - {Source, {command, Message}} -> + {Source, {command, Message}} -> Port ! {self(), {command, Message}}, receive {Port, {data, Result}} -> @@ -72,7 +72,7 @@ loop(Port, Timeout, Command) -> Source ! {self(), {result, X}}, port_close(Port), exit(last_result); - Z -> + Z -> Source ! {self(), Z} end after Timeout -> @@ -82,7 +82,7 @@ loop(Port, Timeout, Command) -> exit(timed_out) end, loop(Port,Timeout,Command); - {_Source, {just_send_a_command, Message}} -> + {_Source, {just_send_a_command, Message}} -> Port ! {self(), {command, Message}}, loop(Port,Timeout,Command); {Port, {exit_status, _Code}} -> @@ -92,11 +92,11 @@ loop(Port, Timeout, Command) -> {'EXIT',_Pid,shutdown} -> port_close(Port), exit(shutdown); - Any -> + Any -> error_logger:warning_msg("PortWrapper ~p got unexpected message: ~p~n", [self(), Any]), loop(Port, Timeout, Command) end. - + % Local API % TODO: Add retry detection diff --git a/elibs/resource_fountain.erl b/elibs/resource_fountain.erl index db14dd7..c13df1d 100644 --- a/elibs/resource_fountain.erl +++ b/elibs/resource_fountain.erl @@ -17,7 +17,7 @@ -include("etest/resource_fountain_test.erl"). -endif. --record(state, {details_pool_dict = dict:new(), +-record(state, {details_pool_dict = dict:new(), pool_details_dict = dict:new(), lookup_cache_dict = dict:new()}). @@ -42,18 +42,18 @@ start() -> % Call to get a pool for a full details spec (often used when offering nodes to the system) % @spec pool_for_details(details()) -> pid() -pool_for_details(Details) -> +pool_for_details(Details) -> gen_server:call({global, ?MODULE}, {pool_for_details, Details}). % Lists all detail specs available in the system. % @spec details_list() -> [details()] -details_list() -> +details_list() -> gen_server:call({global, ?MODULE}, {detail_list}). % Given details and a call, attempts to find the right resource pool to dispatch to. -% This uses best_pool_for_details_match then does call checking. +% This uses best_pool_for_details_match then does call checking. % @spec pool_for_dispatch(call(), details()) -> none | pid() -pool_for_dispatch(Call, PartialDetails) -> +pool_for_dispatch(Call, PartialDetails) -> case best_pool_for_details_match(PartialDetails) of none -> none; Pool -> pool_if_handles_call(Pool, Call) @@ -61,13 +61,13 @@ pool_for_dispatch(Call, PartialDetails) -> % Searches for the best ResourcePool match given a partial set of details. % @spec best_pool_for_details_match(details()) -> none | pid() -best_pool_for_details_match(PartialDetails) -> +best_pool_for_details_match(PartialDetails) -> gen_server:call({global, ?MODULE}, {pool_for_details_match, PartialDetails}). - + identity() -> gen_server:call({global, ?MODULE}, {identity}). - -remove_pool_if_empty(Pool) -> + +remove_pool_if_empty(Pool) -> gen_server:cast({global, ?MODULE}, {remove_pool_if_empty, Pool}). rate_all_pools(Spec) -> @@ -99,20 +99,20 @@ init([]) -> %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- -handle_call({pool_for_details, Details}, _From, State) -> - {Pool, NewState} = find_make_pool_for_details(Details,State#state.lookup_cache_dict,State), +handle_call({pool_for_details, Details}, _From, State) -> + {Pool, NewState} = find_make_pool_for_details(Details,State#state.lookup_cache_dict,State), {reply, Pool, NewState}; -handle_call({detail_list}, _From, State) -> +handle_call({detail_list}, _From, State) -> {reply, dict:fetch_keys(State#state.details_pool_dict), State} ; -handle_call({pool_for_details_match, Details}, _From, State) -> - {{_Score, BestMatch}, NewCache} = - best_details_match_with_caching(Details, +handle_call({pool_for_details_match, Details}, _From, State) -> + {{_Score, BestMatch}, NewCache} = + best_details_match_with_caching(Details, State#state.details_pool_dict, State#state.lookup_cache_dict), if - BestMatch == none -> + BestMatch == none -> {reply, none, State} ; - true -> + true -> {Pool, NewState} = find_make_pool_for_details(BestMatch,NewCache,State), {reply, Pool, NewState} end; @@ -130,10 +130,10 @@ handle_call({rate_all_pools, Spec}, _From, State) -> %%-------------------------------------------------------------------- handle_cast({remove_pool_if_empty, Pool}, #state{details_pool_dict=_DetailsPoolDict, pool_details_dict=PoolDetailsDict, - lookup_cache_dict=_OldCache} = State) when is_pid(Pool) -> + lookup_cache_dict=_OldCache} = State) when is_pid(Pool) -> case lists:member(Pool, dict:fetch_keys(PoolDetailsDict)) of false -> {noreply, State}; % Unrecognized pool - true -> + true -> try {noreply, remove_pool_helper(resource_pool:is_empty(Pool), Pool, State)} catch @@ -155,13 +155,13 @@ remove_pool_helper(true, Pool, #state{details_pool_dict=DetailsPoolDict, case resource_pool:is_logging(Pool) of true -> logger:pool_removed(Pool); false -> ok - end, + end, resource_pool:stop(Pool), PDetails = dict:fetch(Pool, PoolDetailsDict), #state{details_pool_dict=dict:erase(PDetails, DetailsPoolDict), pool_details_dict=dict:erase(Pool, PoolDetailsDict), lookup_cache_dict=dict:new()}. - + %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | @@ -199,7 +199,7 @@ find_make_pool_for_details(Details, NewCache, #state{details_pool_dict=DetailsPoolDict, pool_details_dict=_PoolDetailsDict, - lookup_cache_dict=_OldCache} = State) -> + lookup_cache_dict=_OldCache} = State) -> IsKey = dict:is_key(Details,DetailsPoolDict), if IsKey -> {dict:fetch(Details, DetailsPoolDict), State#state{lookup_cache_dict=NewCache}} ; @@ -224,14 +224,14 @@ introduce_pool_for_details(Details, Cache, #state{details_pool_dict=DetailsPoolD % This function iterates through the details given in the dict() and % finds the details match with the highest score. -best_details_match(Ref, Dict) -> +best_details_match(Ref, Dict) -> Details = dict:fetch_keys(Dict), - FoldFunc = fun(I, {ScTB, Val}) -> + FoldFunc = fun(I, {ScTB, Val}) -> IScore = scoring:score_details(Ref, I), if - IScore > ScTB -> + IScore > ScTB -> {IScore, I}; - true -> + true -> {ScTB, Val} end end, @@ -242,26 +242,26 @@ details_match_list(Ref, Dict) -> MapFunc = fun(I) -> {I, scoring:score_details(Ref, I)} end, [X || {_Item, Score} = X <- lists:map(MapFunc, Details), Score > 0]. -best_details_match_with_caching(Ref, Dict, Cache) -> +best_details_match_with_caching(Ref, Dict, Cache) -> Key = erlang:phash2(Ref), case dict:find(Key, Cache) of {ok, Result} -> {Result, Cache}; - error -> + error -> Result = best_details_match(Ref, Dict), {Result, dict:store(Key, Result, Dict)} end. -cache_lookup_results(Search, Result, Dict) -> +cache_lookup_results(Search, Result, Dict) -> Key = erlang:phash2(Search), case dict:find(Key, Dict) of {ok, _} -> Dict; error -> dict:store(Key, Result, Dict) end. -pool_if_handles_call(Pool, Call) -> +pool_if_handles_call(Pool, Call) -> PoolApi = resource_pool:api_definition(Pool), case lists:keysearch(element(1,Call), 1, PoolApi) of - {value, Callspec} -> + {value, Callspec} -> {RParams, CParams} = {element(2,Call), element(2, Callspec)}, if RParams =:= CParams -> Pool; true -> none diff --git a/elibs/resource_manager.erl b/elibs/resource_manager.erl index e6937ff..dc7b39d 100644 --- a/elibs/resource_manager.erl +++ b/elibs/resource_manager.erl @@ -87,8 +87,8 @@ init([Master, Nodes, Preproc, Postproc, Timeout]) -> process_flag(trap_exit, true), spawn_nodes(Nodes, Preproc, Timeout, dict:new()), {ok, #state{spec = Nodes, - preproc = Preproc, - nodes = dict:new(), + preproc = Preproc, + nodes = dict:new(), postproc = Postproc, timeout = Timeout, master = Master}}. @@ -103,11 +103,11 @@ init([Master, Nodes, Preproc, Postproc, Timeout]) -> %% Description: Handling call messages %%-------------------------------------------------------------------- -handle_call(nodecount,_From,State) -> +handle_call(nodecount,_From,State) -> {reply, length(dict:fetch_keys(State#state.nodes)), State}; handle_call(nodes, _From, State) -> {reply, dict:fetch_keys(State#state.nodes), State}; -handle_call(spec, _From, State) -> +handle_call(spec, _From, State) -> {reply, State#state.spec, State}. %%-------------------------------------------------------------------- @@ -119,26 +119,26 @@ handle_call(spec, _From, State) -> % Node, Setup, Finisher, Registry -handle_cast({add, Cmd, Node}, State) -> +handle_cast({add, Cmd, Node}, State) -> try resource_manager:add_to_fountain(Node) of - _NoOneCares -> + _NoOneCares -> link(Node), % We wuv woo! NewDict = add_node_record(Node, Cmd, State#state.nodes), {noreply, State#state{nodes=NewDict}} catch - _:E -> + _:E -> error_logger:error_msg("Tried to register fresh node ~p with fountain, but failed because: ~p", [Node, E]), {noreply, State} end; -handle_cast(start_fresh_nodes, State) -> +handle_cast(start_fresh_nodes, State) -> spawn_nodes(State#state.spec, State#state.preproc, State#state.timeout, State#state.nodes), {noreply, State}; -handle_cast(stop_all_nodes, State) -> - NodeDict = State#state.nodes, +handle_cast(stop_all_nodes, State) -> + NodeDict = State#state.nodes, RenewNodes = fun(N) -> cease_node(N,State#state.postproc,NodeDict) end, lists:foreach(RenewNodes, dict:fetch_keys(NodeDict)), {noreply, State#state{nodes=dict:new()}}; -handle_cast({change_spec, NewSpec}, State) -> +handle_cast({change_spec, NewSpec}, State) -> {noreply, State#state{spec=NewSpec}}; handle_cast(register_nodes, State) -> error_logger:info_msg("Reconnected to ~p, reregistering nodes now.~n", [State#state.master]), @@ -154,16 +154,16 @@ handle_cast(register_nodes, State) -> %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- -handle_info({'EXIT', Pid, Reason}, State) -> +handle_info({'EXIT', Pid, Reason}, State) -> case dict:is_key(Pid, State#state.nodes) of true -> error_logger:warning_msg("PortWrapper ~p was terminated due to: ~p. Restarting & Heating.", [Pid,Reason]), NewNodeDict = restart_dead_node(Pid,State#state.preproc, State#state.postproc,State#state.timeout,State#state.nodes), {noreply, State#state{nodes=NewNodeDict}}; - false -> + false -> {noreply, State} end; -handle_info(Any,S) -> +handle_info(Any,S) -> error_logger:info_msg("Got INFO ~p~n", [Any]), {noreply, S}. @@ -195,7 +195,7 @@ run_call({Module, Function}, Args) -> apply(Module, Function, listify(Args)); run_call(Function,Args) when is_function(Function) -> apply(Function, listify(Args)). % @spec spawn_linked_node(Cmd, Call) -> {process(), Cmd} -spawn_unlinked_node(Cmd, Call, Timeout) -> +spawn_unlinked_node(Cmd, Call, Timeout) -> Port = port_wrapper:wrap(Cmd, Timeout), case run_call(Call, Port) of ok -> {Port, Cmd}; @@ -208,31 +208,31 @@ erase_node_record(Node, Registry) -> dict:erase(Node, Registry). % @spec spawn_nodes(Nodes::[string()], Registerer::fun(), Registry::dict()) -> dict() spawn_nodes({Cmd, Num}, Setup, Timeout, Registry) -> spawn_nodes(lists:duplicate(Num, Cmd), Setup, Timeout, Registry); spawn_nodes(Nodes, Setup, Timeout, _Registry) when is_list(Nodes) -> - F = fun(Cmd) -> spawn( - fun() -> + F = fun(Cmd) -> spawn( + fun() -> case spawn_unlinked_node(Cmd, Setup, Timeout) of - {error, Cmd} -> + {error, Cmd} -> error_logger:error_msg("Failed to start node with command: ~n~p~n. Resource manager cannot function in this state, system is idle.~nPossible causes include a crash on startup or a timeout on startup. Make sure nodes can start on this machine!", [Cmd]); {Port, Cmd} -> resource_manager:add_node(Port, Cmd) end - end ) + end ) end, lists:foreach(F, Nodes). - -restart_dead_node(Node, Setup, Finisher, Timeout, Registry) -> - % Node is dead, so it should be removed everywhere that + +restart_dead_node(Node, Setup, Finisher, Timeout, Registry) -> + % Node is dead, so it should be removed everywhere that % cares about it, no need to explicitly remove it from % pools. apply(Finisher, [Node]), Cmd = dict:fetch(Node, Registry), NegReg = erase_node_record(Node, Registry), - spawn_nodes([Cmd], Setup, Timeout, NegReg), + spawn_nodes([Cmd], Setup, Timeout, NegReg), NegReg. % @spec renew_node(proc(), dict()) -> dict() -cease_node(Node, Finisher, Registry) -> - try +cease_node(Node, Finisher, Registry) -> + try resource_pool:remove(resource_manager:fountain_pool_for_node(Node),Node) catch _:X -> error_logger:error_msg("Failed to remove node ~p from resource fountain. Reason: ~p", [Node, X]) diff --git a/elibs/resource_pool.erl b/elibs/resource_pool.erl index 8f3dcb6..3f8cab6 100644 --- a/elibs/resource_pool.erl +++ b/elibs/resource_pool.erl @@ -51,7 +51,7 @@ remove(Server, Rsrc) -> % @spec get(pid(), int()) -> resource() | atom() get(Server, Timeout) -> gen_server:cast(Server, {get, self()}), - receive + receive {resource, Rsrc} -> Rsrc after Timeout -> nothing end. @@ -63,7 +63,7 @@ get(Server) -> get(Server, infinity). -% Returns a node to the pool. Will not return a node to the pool +% Returns a node to the pool. Will not return a node to the pool % that has not been added. % @spec refund(pid(), resource()) -> ok | not_a_member refund(Server, Node) -> @@ -87,34 +87,34 @@ list_all_nodes(Server) -> [node(X) || X <- list_all(Server)]. % Show the API of the pools inside. [] if pool is empty and has no details -api_definition(Server) -> +api_definition(Server) -> gen_server:call(Server, {node_api_definition}). % Give the details associated with every node in this pool. % FIXME % spec details(pid()) -> details() -details(Server) -> +details(Server) -> gen_server:call(Server, {details}). % Stop the pool -stop(Server) -> +stop(Server) -> gen_server:cast(Server, {stop}). -is_empty(Server) -> +is_empty(Server) -> length(list_all(Server)) =:= 0. api_signature(Server) -> gen_server:call(Server, {api_signature}). is_logging(Server) -> gen_server:call(Server, {is_logging}). - + set_logging(Server, Logging) -> gen_server:call(Server, {set_logging, Logging}). % %% gen_server callbacks % -init([Details]) -> +init([Details]) -> process_flag(trap_exit, true), Logging = logger:is_pool_logging(self(), Details), {ok, #state{details=Details, logging=Logging}}. @@ -130,40 +130,40 @@ init([Details]) -> %%-------------------------------------------------------------------- handle_call({list}, _Source, State) -> {reply, State#state.active_nodes, State} ; -handle_call({list_all}, _Source, State) -> +handle_call({list_all}, _Source, State) -> {reply, State#state.nodes, State} ; -handle_call({pending_size}, _Source, State) -> +handle_call({pending_size}, _Source, State) -> {reply, length(State#state.pending_requests), State} ; -handle_call({api_signature}, _Source, State) -> +handle_call({api_signature}, _Source, State) -> {reply, State#state.node_api_signature, State}; -handle_call({flush_pending}, _Source, State) -> +handle_call({flush_pending}, _Source, State) -> {reply, length(State#state.pending_requests), State#state{pending_requests=queue:new()}} ; -handle_call({node_api_definition}, _Source, State) -> +handle_call({node_api_definition}, _Source, State) -> {reply, State#state.node_api_definition, State}; -handle_call({details}, _Source, State) -> +handle_call({details}, _Source, State) -> {reply, State#state.details, State}; handle_call({is_logging}, _Source, State) -> {reply, State#state.logging, State}; handle_call({set_logging, Logging}, _Source, State) -> {reply, ok, State#state{logging=Logging}}; -handle_call({refund, Resource}, _Source, State) -> +handle_call({refund, Resource}, _Source, State) -> % Only work if this node is actually a member of the pool IsMember = lists:member(Resource, State#state.nodes), - if IsMember -> + if IsMember -> QueueIsEmpty = queue:is_empty(State#state.pending_requests), if QueueIsEmpty -> {reply, ok, State#state{active_nodes=lists:append(State#state.active_nodes, [Resource])}} ; - true -> + true -> {{value, Waiting}, NewQueue} = queue:out(State#state.pending_requests), Waiting ! {resource, Resource}, {reply, ok, State#state{pending_requests=NewQueue}} end ; - true -> + true -> {reply, not_a_member, State} end. - - - + + + %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | @@ -171,7 +171,7 @@ handle_call({refund, Resource}, _Source, State) -> %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- -handle_cast({stop}, State) -> +handle_cast({stop}, State) -> {stop, shutdown, State}; handle_cast({remove, Rsrc}, State) -> if State#state.logging -> logger:node_left(self(), Rsrc); @@ -180,7 +180,7 @@ handle_cast({remove, Rsrc}, State) -> resource_fountain:remove_pool_if_empty(self()), {noreply, State#state{ nodes=lists:delete(Rsrc, State#state.nodes), active_nodes=lists:delete(Rsrc, State#state.active_nodes)}}; -handle_cast({add, Rsrc}, State) -> +handle_cast({add, Rsrc}, State) -> if State#state.logging -> logger:node_joined(self(), Rsrc); true -> ok end, @@ -188,9 +188,9 @@ handle_cast({add, Rsrc}, State) -> link(Rsrc), {noreply, NewState}; -handle_cast({get, For}, State) -> - if - length(State#state.active_nodes) > 0 -> +handle_cast({get, For}, State) -> + if + length(State#state.active_nodes) > 0 -> [Head|Rest] = State#state.active_nodes, For ! {resource, Head}, {noreply, State#state{active_nodes=Rest}} ; @@ -198,14 +198,14 @@ handle_cast({get, For}, State) -> Q = queue:in(For, State#state.pending_requests), {noreply, State#state{pending_requests=Q}} end. - -handle_info({'EXIT', Pid, _Reason}, State) -> + +handle_info({'EXIT', Pid, _Reason}, State) -> if State#state.logging -> logger:node_left(self(), Pid); true -> ok end, {noreply, State#state{ nodes=lists:delete(Pid, State#state.nodes), active_nodes=lists:delete(Pid, State#state.active_nodes)}}; -handle_info(Any,S) -> +handle_info(Any,S) -> error_logger:info_msg("Got INFO ~p~n", [Any]), {noreply, S}. @@ -226,24 +226,24 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. - + %%-------------------------------------------------------------------- %% Internal API calls %%-------------------------------------------------------------------- -insert_matching_node_once(Node, #state{nodes=[]} = State) -> +insert_matching_node_once(Node, #state{nodes=[]} = State) -> pool_sweeper:watch(self(), Node), - State#state{nodes=[Node], active_nodes=[Node], + State#state{nodes=[Node], active_nodes=[Node], node_api_signature=node_api:api_signature(Node), node_api_definition=node_api:api(Node), details=node_api:details(Node)}; -insert_matching_node_once(Node, State) -> +insert_matching_node_once(Node, State) -> {Nodes, ActiveNodes} = {State#state.nodes, State#state.active_nodes}, NodeApiSignature = node_api:api_signature(Node), if - NodeApiSignature =:= State#state.node_api_signature -> + NodeApiSignature =:= State#state.node_api_signature -> pool_sweeper:watch(self(), Node), State#state{nodes=lists:umerge(Nodes, [Node]), active_nodes=lists:umerge(ActiveNodes, [Node])}; - true -> + true -> State end. diff --git a/elibs/responders/api_responder.erl b/elibs/responders/api_responder.erl index 3e92a0e..7a54126 100644 --- a/elibs/responders/api_responder.erl +++ b/elibs/responders/api_responder.erl @@ -17,7 +17,7 @@ yaws_extract_details(Arg) -> false -> [] ; {value, {_, V}} -> V end. - + yaws_handler(_State, {call, Method, Value} = _Request, _Session) -> Result = rpc_translator(Method,Value), {true, 0, hello, Result}. @@ -43,6 +43,6 @@ rpc_translator(Method, TupleList) -> response_error_logger:log_error({Details, ApiSpec}, Result), {error, Result} end. - + build_api_spec(Method,Params) -> {Method, list_to_tuple(lists:sort([X || {X, _} <- Params]))}. diff --git a/elibs/responders/frontend_responder.erl b/elibs/responders/frontend_responder.erl index 3764159..569710d 100644 --- a/elibs/responders/frontend_responder.erl +++ b/elibs/responders/frontend_responder.erl @@ -14,7 +14,7 @@ provide_pool() -> %% provide_pool(A, _GC, _SC) -> %% % I confess this approach is lazy, but I don't think it's slow. %% case application:get_env(fuzed_frontend, current_pool) of -%% undefined -> +%% undefined -> %% Pool = lookup_and_cache_pool(), %% {Pool, A}; %% {ok, Pool} -> @@ -25,7 +25,7 @@ provide_pool() -> %% case is_remote_process_alive(Pool) of %% true -> %% {Pool, A}; -%% false -> +%% false -> %% {lookup_and_cache_pool(), A} %% end %% end @@ -34,7 +34,7 @@ provide_pool() -> %% lookup_and_cache_pool() -> %% Pool = resource_fountain:best_pool_for_details_match(details()), %% case Pool of -%% none -> +%% none -> %% application:set_env(fuzed_frontend, current_pool, undefined), %% none; %% X -> diff --git a/elibs/responders/master_responder.erl b/elibs/responders/master_responder.erl index 7776c07..9d8d95c 100644 --- a/elibs/responders/master_responder.erl +++ b/elibs/responders/master_responder.erl @@ -19,7 +19,7 @@ out(A) -> % compliance with the true JSON-RPC spec yaws_jsonrpc:handler_session(A2, {?MODULE, yaws_handler}). -yaws_handler(_State, {call, Method, Value} = _Request, _Session) -> +yaws_handler(_State, {call, Method, Value} = _Request, _Session) -> Result = rpc_translator(Method,Value), {true, 0, hello, Result}. %% END Yaws Specific Stuff @@ -29,12 +29,12 @@ mochiweb_handler(_Req, {call, Method, {struct, TupleList}}) -> rpc_translator(Method, TupleList). %% END Mochiweb Specific Stuff -rpc_translator(Method, TupleList) -> +rpc_translator(Method, TupleList) -> Details = k(details, TupleList), Parameters = d(details, TupleList), ApiSpec = build_api_spec(Method,Parameters), case Method of - list_available_configurations -> + list_available_configurations -> AvailableDetails = resource_fountain:details_list(), {result, {array, [jsonify_full_details_list(IndividualDetail) || IndividualDetail <- AvailableDetails]}}; configuration_for_details -> @@ -48,12 +48,12 @@ rpc_translator(Method, TupleList) -> exception_logging_disable -> response_error_logger:set_active(false), {result, <<"Logging Disabled.">>}; - current_pool_traces -> + current_pool_traces -> {result, jsonify_full_details_list(logger:list_details_selectors())}; - start_pool_trace -> + start_pool_trace -> logger:enable_logging(Details), {result, "Trace added."}; - stop_pool_trace -> + stop_pool_trace -> logger:disable_logging(Details), {result, "Trace removed."}; available_methods -> @@ -81,13 +81,13 @@ rpc_translator(Method, TupleList) -> case node_api:safely_send_call_to_pool(Method, Parameters, ApiSpec, json, Details) of {result, R} -> {result, R}; {error, R} -> response_error_logger:log_error( - {Details, ApiSpec}, + {Details, ApiSpec}, R), {error, R} end end. - + % convenience/helper functions k(_Key, []) -> ""; @@ -96,7 +96,7 @@ k(Key, List) when is_atom(Key) -> k_halp(Key, List); k(Key, List) when is_list(Key) -> K = list_to_atom(Key), k_halp(K,List). -k_halp(Key, List) -> +k_halp(Key, List) -> case lists:keysearch(Key, 1, List) of {value, {Key, Val}} -> Val ; Else -> Else @@ -109,18 +109,18 @@ d(Var, Keylist) -> lists:keydelete(Var, 1, Keylist). normalize_details({struct, DetailTuples}) -> [normalize_detail_tuple(X) || X <- DetailTuples]. atom_to_binary(Atom) when is_atom(Atom) -> list_to_binary(atom_to_list(Atom)). -string_to_bound_int(String) -> +string_to_bound_int(String) -> case io_lib:fread("~d", String) of {ok, [Result], _} -> Result; {error, _} -> 0 end. % @spec string_to_version_tuple(string()) -> {int(),int(),int(),int()} -string_to_version_tuple(String) -> +string_to_version_tuple(String) -> list_to_4_tup([string_to_bound_int(X) || X <- string:tokens(String, ".-")]). % @spec process_detail_rval(string()) -> {int(),int(),int(),int()} | binary() -process_detail_rval(String) -> +process_detail_rval(String) -> case string:str(String,".") of 0 -> list_to_binary(String); _ -> string_to_version_tuple(String) diff --git a/elibs/response_error_logger.erl b/elibs/response_error_logger.erl index e72a2e6..a616f43 100644 --- a/elibs/response_error_logger.erl +++ b/elibs/response_error_logger.erl @@ -87,5 +87,5 @@ write_error({Details, ApiReq}, ErrorStr, FileHandle) -> now_string() -> {{_, Month, Day}, {Hour, Minute, Second}} = erlang:localtime(), io_lib:format("~p-~p (~p:~p:~p)", [Month, Day, Hour, Minute, Second]). - + diff --git a/elibs/scoring.erl b/elibs/scoring.erl index 8a0c228..78814a3 100644 --- a/elibs/scoring.erl +++ b/elibs/scoring.erl @@ -8,40 +8,40 @@ % This function tries to score a partial details spec (Ref) vs. a full details spec (Details). % @spec score_details(details(), details()) -> int() -score_details(Ref, Details) -> +score_details(Ref, Details) -> RoleMatchScore = role_match_score(Ref, Details), VersionMatchScore = version_match_score(Ref, Details), TagBonusScore = tag_bonus_score(Ref, Details), RoleMatchScore + VersionMatchScore + TagBonusScore. - + % Extract a specific key's contents from a details list. % @spec extract(binary(), details()) -> nil() | [binary()] -extract(Key, Details) -> +extract(Key, Details) -> case lists:keysearch(Key, 1, Details) of {value, {Key, V}} -> V ; false -> [] end. - + % Calculate role matching score. A perfect role match scores 0, % anything else scores -1000 % @spec role_match_score(details(), details()) -> int() -role_match_score(Ref, Details) -> +role_match_score(Ref, Details) -> RefRoles = extract(<<"roles">>, Ref), DetailsRoles = extract(<<"roles">>, Details), case lists:sort(RefRoles) =:= lists:sort(DetailsRoles) of true -> 0; false -> -1000 end. - + % Calculate version matching score. Matches get 1 points, % conflicts get -1000 % @spec version_match_score(details(), details()) -> int() -version_match_score(Ref, Details) -> - FoldFunc = fun({K, V}, A) -> +version_match_score(Ref, Details) -> + FoldFunc = fun({K, V}, A) -> case lists:keysearch(K, 1, Details) of false -> A; {value, {K, Value}} -> - if + if Value == V -> A + 1 ; true -> -1000 end @@ -51,7 +51,7 @@ version_match_score(Ref, Details) -> % Does the special tag calculation on a pair of details. Assists score_details. % @spec calculate_tag_bonus(details(), details()) -> int() -tag_bonus_score(Ref, Details) -> +tag_bonus_score(Ref, Details) -> RefTags = extract(<<"tags">>, Ref), DetailsTags = extract(<<"tags">>, Details), length([X || X <- RefTags, lists:member(X, DetailsTags)]). \ No newline at end of file diff --git a/elibs/servers/yaws/yaws_frontend.erl b/elibs/servers/yaws/yaws_frontend.erl index 024271f..e4d55ac 100644 --- a/elibs/servers/yaws/yaws_frontend.erl +++ b/elibs/servers/yaws/yaws_frontend.erl @@ -7,7 +7,7 @@ start(IP, Port, DocRoot, SSL, ResponderModule, FrameworkModule, AppModSpecs) -> application:set_env(yaws, embedded, true), application:start(yaws), yaws_api:setconf(GC, [[SC]]). - + start(Conf) -> Env = #env{conf = {file, Conf}, debug = false, @@ -30,9 +30,9 @@ yaws_gc() -> trace = false, logdir = "./log", cache_refresh_secs = 30, - flags = ?GC_AUTH_LOG bor - ?GC_COPY_ERRLOG bor - ?GC_FAIL_ON_BIND_ERR bor + flags = ?GC_AUTH_LOG bor + ?GC_COPY_ERRLOG bor + ?GC_FAIL_ON_BIND_ERR bor ?GC_PICK_FIRST_VIRTHOST_ON_NOMATCH, yaws = "Yaws " ++ yaws_generated:version(), id = genericID @@ -46,7 +46,7 @@ yaws_global_configs(IP, Port, DocRoot, SSL, ResponderModule, FrameworkModule, Ap SC = #sconf{port = Port, servername = atom_to_list(ResponderModule), listen = IP, - docroot = DocRoot, + docroot = DocRoot, errormod_404 = ResponderModule, errormod_crash = FrameworkModule, appmods = AppModModules, @@ -57,13 +57,13 @@ yaws_global_configs(IP, Port, DocRoot, SSL, ResponderModule, FrameworkModule, Ap SC2 = SC#sconf{ssl = #ssl{keyfile = Key, certfile = Cert}}; none -> SC2 = SC - end, + end, {GC,SC2}. % Triples: {Path, module, Role} prepare_appmod_data(AppMods) when is_list(AppMods) -> - lists:foldl(fun({Path, Module, Role}, {AMMM, Opaques}) -> - {[{to_string(Path), Module}|AMMM], + lists:foldl(fun({Path, Module, Role}, {AMMM, Opaques}) -> + {[{to_string(Path), Module}|AMMM], [{{to_string(Path), Module}, [{<<"roles">>, [to_binary(Role)]}]}|Opaques]} end, {[], []}, diff --git a/elibs/servers/yaws/yaws_master.erl b/elibs/servers/yaws/yaws_master.erl index 0b47447..2834b74 100644 --- a/elibs/servers/yaws/yaws_master.erl +++ b/elibs/servers/yaws/yaws_master.erl @@ -10,7 +10,7 @@ start(IP, Port, DocRoot) -> yaws_api:setconf(GC, [[SC]]). -yaws_global_configs(IP, Port, DocRoot) -> +yaws_global_configs(IP, Port, DocRoot) -> Y = yaws_config:yaws_dir(), GC = #gconf{yaws_dir = Y, ebin_dir = [filename:join([Y, "examples/ebin"])], @@ -26,7 +26,7 @@ yaws_global_configs(IP, Port, DocRoot) -> SC = #sconf{port = Port, servername = "master_responder", listen = IP, - docroot = DocRoot, + docroot = DocRoot, appmods = [{"api", master_responder}, {"status", status_responder}]}, {GC,SC}. diff --git a/etest/master_responder_test.erl b/etest/master_responder_test.erl index 2e09525..82beb0b 100644 --- a/etest/master_responder_test.erl +++ b/etest/master_responder_test.erl @@ -3,17 +3,17 @@ % HELPERS % % atom_to_binary -atom_to_binary_test() -> +atom_to_binary_test() -> <<"hello">> = atom_to_binary(hello). % normalize_details_tuple -ndt_basic_test() -> +ndt_basic_test() -> [DTs, DTi, DTm] = [{bears, "1.2.3-1"}, {beets, 0}, {bg, "1.2.3"}], {<<"bears">>, {1, 2, 3, 1}} = normalize_detail_tuple(DTs), {<<"beets">>, <<"0">>} = normalize_detail_tuple(DTi), {<<"bg">>, {1,2,3}} = normalize_detail_tuple(DTm). -ndt_tags_test() -> +ndt_tags_test() -> [_DTs, _DTi, DTt] = [{bears, "yes"}, {beets, 0}, {tags, "one,two,three"}], {<<"tags">>, [<<"one">>, <<"two">>, <<"three">>]} = normalize_detail_tuple(DTt). @@ -24,18 +24,18 @@ uql_test_test() -> L2 = uniquify_list(L1). % k() -k_does_basics_test() -> +k_does_basics_test() -> L1 = [{bears, "Hello!"}, {beets, "WORLD!"}], "Hello!" = k(bears, L1), "WORLD!" = k(beets, L1), false = k(bsg, L1). - -k_does_term_translation_test() -> + +k_does_term_translation_test() -> L1 = [{bears, "Hello!"}, {beets, "WORLD!"}], "Hello!" = k("bears", L1), false = k("bsg", L1). -k_does_details_right_test() -> +k_does_details_right_test() -> Details = [{xle, "1.2.3-4"}, {tags, "one"}], L1 = [{details, {struct, Details}}, {notdetails, "Fakeness"}], [{<<"xle">>, {1,2,3,4}}, {<<"tags">>, [<<"one">>]}] = k(details, L1). diff --git a/etest/node_api_test.erl b/etest/node_api_test.erl index c7d6b7c..beea9ec 100644 --- a/etest/node_api_test.erl +++ b/etest/node_api_test.erl @@ -1,27 +1,27 @@ -include_lib("eunit/eunit.hrl"). -basic_conversion_test() -> +basic_conversion_test() -> V1 = [{passage, "This is my boomstick"}, {options, ""}], V2 = [{passage, <<"This is my boomstick">>}, {options, <<"">>}], V2 = prepare_parameters(V1). - - -array_conversion_test() -> + + +array_conversion_test() -> V1 = [{key, {array, [<<"value1">>, <<"value2">>]}}], V2 = [{key, {array, [<<"value1">>, <<"value2">>]}}], V2 = prepare_parameters(V1). - -struct_converstion_test() -> + +struct_converstion_test() -> V1 = [{options, {struct, [{restrict_to_url, "Test me!"}]}}], V2 = [{options, {struct, [{restrict_to_url, <<"Test me!">>}]}}], V2 = prepare_parameters(V1). -nested_struct_array_conversion_test() -> - V1 = [{options, +nested_struct_array_conversion_test() -> + V1 = [{options, {struct, [ {restrict_to_url, {struct, [{key, <<"Test me!">>}]}}]}}], - V2 = [{options, + V2 = [{options, {struct, [ {restrict_to_url, {struct, [{key, <<"Test me!">>}]}}]}}], V2 = prepare_parameters(V1). - + diff --git a/etest/scoring_test.erl b/etest/scoring_test.erl index 9bce1de..8f850fa 100644 --- a/etest/scoring_test.erl +++ b/etest/scoring_test.erl @@ -4,15 +4,15 @@ score_details_should_return_0_for_empty_details_test() -> 0 = score_details([], []). - + score_details_should_return_1_for_single_tag_match_test() -> D1 = [{<<"tags">>, [<<"foobar">>]}], 1 = score_details(D1, D1). - + score_details_should_return_n_for_n_tag_match_test() -> D1 = [{<<"tags">>, [<<"foo">>, <<"bar">>, <<"baz">>]}], 3 = score_details(D1, D1). - + score_details_should_return_1_for_single_version_match_test() -> D1 = [{<<"alpha">>, <<"1.2.3">>}], D2 = [{<<"alpha">>, <<"1.2.3">>}, {<<"beta">>, <<"5.5.5">>}], @@ -24,25 +24,25 @@ score_details_should_return_2_for_mixed_type_test() -> D2 = [{<<"alpha">>, <<"1.2.3">>}, {<<"beta">>, <<"5.5.5">>}, {<<"gramma">>, <<"query">>}], 2 = score_details(D1, D1), 2 = score_details(D1, D2). - + score_details_should_return_minus_1000_for_non_match_test() -> D1 = [{<<"alpha">>, <<"1.2.3">>}], D2 = [{<<"alpha">>, <<"3.2.1">>}], -1000 = score_details(D1, D2). - + extract_should_extract_single_tag_list_test() -> Tag = extract(<<"tags">>, [{<<"tags">>, [<<"foobar">>]}]), [<<"foobar">>] = Tag. - + extract_should_extract_multiple_tag_list_test() -> Tag = extract(<<"tags">>, [{<<"tags">>, [<<"foo">>, <<"bar">>]}]), [<<"foo">>, <<"bar">>] = Tag. - + extract_should_return_nil_if_not_matching_tags_test() -> Tag = extract(<<"tags">>, [{<<"bogus">>, [<<"foobar">>]}]), [] = Tag. - + % role_match_score role_match_score_should_return_0_for_perfect_match_test() -> @@ -52,13 +52,13 @@ role_match_score_should_return_0_for_perfect_match_test() -> 0 = role_match_score(D0, D0), 0 = role_match_score(D1, D1), 0 = role_match_score(D2, D2). - + role_match_score_should_return_minus_1000_for_non_match_test() -> D1 = [{<<"roles">>, [<<"foo">>]}], D2 = [{<<"roles">>, [<<"foo">>, <<"bar">>]}], -1000 = role_match_score(D1, D2), -1000 = role_match_score(D2, D1). - + % tag_bonus_score tag_bonus_score_should_give_one_point_for_each_match_test() -> diff --git a/include/eunit/eunit.hrl b/include/eunit/eunit.hrl index b1d2274..b072b81 100644 --- a/include/eunit/eunit.hrl +++ b/include/eunit/eunit.hrl @@ -60,7 +60,7 @@ %% All macros should be available even if testing is turned off, and %% should preferably not require EUnit to be present at runtime. -%% +%% %% We must use fun-call wrappers ((fun () -> ... end)()) to avoid %% exporting local variables, and furthermore we only use variable names %% prefixed with "__", that hopefully will not be bound outside the fun. diff --git a/include/responder_base.erl b/include/responder_base.erl index 3788062..501760f 100644 --- a/include/responder_base.erl +++ b/include/responder_base.erl @@ -29,13 +29,13 @@ yaws_process_arg(Arg, SC) -> {https, determine_ssl(SC)}, {remote_addr, yaws_prepare(remote_addr, Arg)}, {querypath, yaws_prepare(querypath, Arg)}, - {querydata, prep(Arg#arg.querydata)}, + {querydata, prep(Arg#arg.querydata)}, {servername, prep(SC#sconf.servername)}, {headers, {struct, yaws_prepare_headers(Headers)}}, {cookies, {array, lists:map(fun(X) -> prep(X) end, Headers#headers.cookie)}}, {pathinfo, prep(SC#sconf.docroot)}, {postdata, Arg#arg.clidata}]. - + yaws_prepare(method, Arg) -> {http_request, Method, {_Type, _Path}, _Version} = Arg#arg.req, Method; @@ -52,7 +52,7 @@ yaws_prepare(remote_addr, Arg) -> catch _:_ -> ok end. - + get_remote_addr(Socket) -> Peer = inet:peername(Socket), case Peer of @@ -85,8 +85,8 @@ yaws_prepare_headers(Headers) -> {content_encoding, prep(Headers#headers.content_encoding)}, {authorization, prep_authorization(Headers#headers.authorization)}, {transfer_encoding, prep(Headers#headers.transfer_encoding)}], - SpecialHeaders = - lists:map(fun({http_header, _Len, Name, _, Value}) -> {prep(Name), prep(Value)} end, + SpecialHeaders = + lists:map(fun({http_header, _Len, Name, _, Value}) -> {prep(Name), prep(Value)} end, Headers#headers.other), [{Name, Res} || {Name, Res} <- NormalHeaders, Res /= undefined] ++ SpecialHeaders. %% END Yaws Specific Stuff @@ -142,7 +142,7 @@ mochiweb_parse_request(Req, DocRoot) -> {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), Cookies = [list_to_binary(lists:flatten(Key ++ "=" ++ Value)) || {Key, Value} <- Req:parse_cookie()], Headers = mochiweb_prepare_headers(mochiweb_headers:to_list(Req:get(headers))), - + [{method, Req:get(method)}, {http_version, {array, tuple_to_list(Req:get(version))}}, {querypath, list_to_binary(RawPath)}, @@ -171,7 +171,7 @@ determine_ssl(SC) -> undefined -> 0; _Else -> 1 end. - + execute_request(Pool, Parameters) -> case node_api:safely_send_call_to_pool_no_lookup(handle_request, Parameters, pure, Pool) of {result, Result} -> result_processor(Result); diff --git a/include/yaws/erlsom.hrl b/include/yaws/erlsom.hrl index 299d956..62dd10f 100644 --- a/include/yaws/erlsom.hrl +++ b/include/yaws/erlsom.hrl @@ -1,11 +1,11 @@ %%% ==================================================================== %%% Header file for erlsom -%%% +%%% %%% Copyright (C) 2006 Willem de Jong %%% %%% This program is free software; you can redistribute it and/or modify -%%% it under the terms of the GNU General Public License as published by -%%% the Free Software Foundation; either version 2 of the License, or +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% This program is distributed in the hope that it will be useful, but @@ -13,8 +13,8 @@ %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %%% General Public License for more details. %%% -%%% You should have received a copy of the GNU General Public License -%%% along with this program; if not, write to the Free Software +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %%% USA %%% diff --git a/include/yaws/yaws.hrl b/include/yaws/yaws.hrl index 171711f..c40ef2e 100644 --- a/include/yaws/yaws.hrl +++ b/include/yaws/yaws.hrl @@ -1,7 +1,7 @@ %%%---------------------------------------------------------------------- %%% File : yaws.hrl %%% Author : Claes Wikstrom -%%% Purpose : +%%% Purpose : %%% Created : 16 Jan 2002 by Claes Wikstrom %%%---------------------------------------------------------------------- @@ -9,7 +9,7 @@ -%% flags for gconfs +%% flags for gconfs -define(GC_TTY_TRACE, 1). -define(GC_DEBUG, 2). -define(GC_AUTH_LOG, 4). @@ -24,19 +24,19 @@ -define(GC_DEF, (?GC_AUTH_LOG bor ?GC_FAIL_ON_BIND_ERR)). --define(gc_has_tty_trace(GC), +-define(gc_has_tty_trace(GC), ((GC#gconf.flags band ?GC_TTY_TRACE) /= 0)). --define(gc_has_debug(GC), +-define(gc_has_debug(GC), ((GC#gconf.flags band ?GC_DEBUG) /= 0)). --define(gc_has_auth_log(GC), +-define(gc_has_auth_log(GC), ((GC#gconf.flags band ?GC_AUTH_LOG) /= 0)). --define(gc_has_copy_errlog(GC), +-define(gc_has_copy_errlog(GC), ((GC#gconf.flags band ?GC_COPY_ERRLOG) /= 0)). --define(gc_has_backwards_compat_parse(GC), +-define(gc_has_backwards_compat_parse(GC), ((GC#gconf.flags band ?GC_BACKWARDS_COMPAT_PARSE) /= 0)). --define(gc_log_has_resolve_hostname(GC), +-define(gc_log_has_resolve_hostname(GC), ((GC#gconf.flags band ?GC_LOG_RESOLVE_HOSTNAME) /= 0)). --define(gc_fail_on_bind_err(GC), +-define(gc_fail_on_bind_err(GC), ((GC#gconf.flags band ?GC_FAIL_ON_BIND_ERR) /= 0)). -define(gc_pick_first_virthost_on_nomatch(GC), ((GC#gconf.flags band ?GC_PICK_FIRST_VIRTHOST_ON_NOMATCH) /= 0)). @@ -45,28 +45,28 @@ -define(gc_use_old_ssl(GC), ((GC#gconf.flags band ?GC_USE_OLD_SSL) /= 0)). --define(gc_set_tty_trace(GC, Bool), +-define(gc_set_tty_trace(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags,?GC_TTY_TRACE, Bool)}). --define(gc_set_debug(GC, Bool), +-define(gc_set_debug(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_DEBUG, Bool)}). --define(gc_set_auth_log(GC, Bool), +-define(gc_set_auth_log(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_AUTH_LOG, Bool)}). --define(gc_set_copy_errlog(GC, Bool), +-define(gc_set_copy_errlog(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_COPY_ERRLOG, Bool)}). --define(gc_set_backwards_compat_parse(GC, Bool), - GC#gconf{flags = yaws:flag(GC#gconf.flags, +-define(gc_set_backwards_compat_parse(GC, Bool), + GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_BACKWARDS_COMPAT_PARSE, Bool)}). --define(gc_log_set_resolve_hostname(GC, Bool), - GC#gconf{flags = yaws:flag(GC#gconf.flags, +-define(gc_log_set_resolve_hostname(GC, Bool), + GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_LOG_RESOLVE_HOSTNAME, Bool)}). --define(gc_set_fail_on_bind_err(GC, Bool), +-define(gc_set_fail_on_bind_err(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags,?GC_FAIL_ON_BIND_ERR,Bool)}). --define(gc_set_pick_first_virthost_on_nomatch(GC, Bool), +-define(gc_set_pick_first_virthost_on_nomatch(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags, ?GC_PICK_FIRST_VIRTHOST_ON_NOMATCH,Bool)}). --define(gc_set_use_fdsrv(GC, Bool), +-define(gc_set_use_fdsrv(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags,?GC_USE_FDSRV,Bool)}). --define(gc_set_use_old_ssl(GC, Bool), +-define(gc_set_use_old_ssl(GC, Bool), GC#gconf{flags = yaws:flag(GC#gconf.flags,?GC_USE_OLD_SSL,Bool)}). @@ -75,7 +75,7 @@ -record(gconf,{yaws_dir, %% topdir of Yaws installation trace, %% false | {true,http}|{true,traffic} flags = ?GC_DEF, %% boolean flags - logdir, + logdir, ebin_dir = [], runmods = [], %% runmods for entire server keepalive_timeout = 15000, @@ -85,16 +85,16 @@ large_file_chunk_size = 10240, log_wrap_size = 10000000, % wrap logs after 10M cache_refresh_secs = 30, % seconds (auto zero when debug) - include_dir = [], %% list of inc dirs for .yaws files + include_dir = [], %% list of inc dirs for .yaws files phpexe = "/usr/bin/php-cgi", %% cgi capable php executable yaws, %% server string id = "default", %% string identifying this instance of yaws enable_soap = false %% start yaws_soap_srv iff true - }). + }). --record(ssl, +-record(ssl, { keyfile, certfile, @@ -117,15 +117,15 @@ -define(SC_DEF, ?SC_ACCESS_LOG bor ?SC_ADD_PORT). --define(sc_has_access_log(SC), +-define(sc_has_access_log(SC), (((SC)#sconf.flags band ?SC_ACCESS_LOG) /= 0)). --define(sc_has_add_port(SC), +-define(sc_has_add_port(SC), (((SC)#sconf.flags band ?SC_ADD_PORT) /= 0)). -define(sc_has_tilde_expand(SC), (((SC)#sconf.flags band ?SC_TILDE_EXPAND) /= 0)). -define(sc_has_dir_listings(SC), (((SC)#sconf.flags band ?SC_DIR_LISTINGS) /= 0)). --define(sc_has_deflate(SC), +-define(sc_has_deflate(SC), (((SC)#sconf.flags band ?SC_DEFLATE) /= 0)). -define(sc_has_dir_all_zip(SC), (((SC)#sconf.flags band ?SC_DIR_ALL_ZIP) /= 0)). @@ -133,21 +133,21 @@ (((SC)#sconf.flags band ?SC_DAV) /= 0)). --define(sc_set_access_log(SC, Bool), +-define(sc_set_access_log(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_ACCESS_LOG, Bool)}). --define(sc_set_add_port(SC, Bool), +-define(sc_set_add_port(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_ADD_PORT, Bool)}). --define(sc_set_ssl(SC, Bool), +-define(sc_set_ssl(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags , ?SC_SSL, Bool)}). --define(sc_set_tilde_expand(SC, Bool), +-define(sc_set_tilde_expand(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_TILDE_EXPAND, Bool)}). --define(sc_set_dir_listings(SC, Bool), +-define(sc_set_dir_listings(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DIR_LISTINGS, Bool)}). --define(sc_set_deflate(SC, Bool), +-define(sc_set_deflate(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DEFLATE, Bool)}). --define(sc_set_dir_all_zip(SC, Bool), +-define(sc_set_dir_all_zip(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DIR_ALL_ZIP, Bool)}). --define(sc_set_dav(SC, Bool), +-define(sc_set_dav(SC, Bool), SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DAV, Bool)}). @@ -168,7 +168,7 @@ authdirs = [], partial_post_size = nolimit, appmods = [], %% list of modules for this app - errormod_404 = yaws_404, %% the default 404 error module + errormod_404 = yaws_404, %% the default 404 error module errormod_crash = yaws_404, %% use the same module for crashes arg_rewrite_mod = yaws, opaque = [], %% useful in embedded mode @@ -196,14 +196,14 @@ %% this internal record is used and returned by the URL path parser --record(urltype, {type, %% error | yaws | regular | directory | - %% forbidden | appmod +-record(urltype, {type, %% error | yaws | regular | directory | + %% forbidden | appmod finfo, path = [], fullpath = [], %% deep list (WHY?) dir = [], %% relative dir where the path leads to %% flat | unflat need flat for authentication - data, %% type-specific e.g: Binary | FileDescriptor + data, %% type-specific e.g: Binary | FileDescriptor %% | DirListing | undefined deflate, %% undefined | Binary | dynamic mime = "text/html", %% MIME type @@ -249,7 +249,7 @@ }). - + -define(READ_TIMEOUT, 30000). @@ -261,7 +261,7 @@ %% as read by application:get_env() --record(env, {debug, +-record(env, {debug, trace, traceoutput, conf, diff --git a/include/yaws/yaws_api.hrl b/include/yaws/yaws_api.hrl index 02c7fec..5356253 100644 --- a/include/yaws/yaws_api.hrl +++ b/include/yaws/yaws_api.hrl @@ -1,7 +1,7 @@ %%%---------------------------------------------------------------------- %%% File : yaws_api.hrl %%% Author : Claes Wikstrom -%%% Purpose : +%%% Purpose : %%% Created : 24 Jan 2002 by Claes Wikstrom %%%---------------------------------------------------------------------- @@ -13,11 +13,11 @@ headers, %% headers req, %% request clidata, %% The client data (as a binary in POST requests) - server_path, %% The normalized server path + server_path, %% The normalized server path %% (pre-querystring part of URI) - querydata, %% For URIs of the form ...?querydata + querydata, %% For URIs of the form ...?querydata %% equiv of cgi QUERY_STRING - appmoddata, %% (deprecated - use pathinfo instead) the remainder + appmoddata, %% (deprecated - use pathinfo instead) the remainder %% of the path leading up to the query docroot, %% Physical base location of data for this request docroot_mount, %% virtual directory e.g /myapp/ that the docroot @@ -27,13 +27,13 @@ state, %% State for use by users of the out/1 callback pid, %% pid of the yaws worker process opaque, %% useful to pass static data - appmod_prepath, %% (deprecated - use prepath instead) path in front + appmod_prepath, %% (deprecated - use prepath instead) path in front %%of: - prepath, %% Path prior to 'dynamic' segment of URI. - %% ie http://some.host///d/e - %% where is an appmod mount point, + prepath, %% Path prior to 'dynamic' segment of URI. + %% ie http://some.host///d/e + %% where is an appmod mount point, %% or .yaws,.php,.cgi etc script file. - pathinfo %% Set to '/d/e' when calling c.yaws for the request + pathinfo %% Set to '/d/e' when calling c.yaws for the request %% http://some.host/a/b/c.yaws/d/e %% equiv of cgi PATH_INFO }). @@ -76,16 +76,16 @@ -record(url, {scheme, - host, + host, port, %% undefined means not set path = [], querypart = []}). -record(setcookie,{ - key, - value, - quoted, + key, + value, + quoted, comment, comment_url, discard, @@ -101,4 +101,4 @@ - + diff --git a/rlibs/adder_node.rb b/rlibs/adder_node.rb index 57549d3..cade235 100644 --- a/rlibs/adder_node.rb +++ b/rlibs/adder_node.rb @@ -12,7 +12,7 @@ class FakeHandler < Chassis handle(:add, :arg1, :arg2) do |args| args[:arg1] + args[:arg2] end - + handle(:crash) do |args| raise "You asked me to crash, so I did." end diff --git a/rlibs/chassis.rb b/rlibs/chassis.rb index 92c63e3..164da31 100644 --- a/rlibs/chassis.rb +++ b/rlibs/chassis.rb @@ -7,7 +7,7 @@ class Chassis class << self attr_accessor :signatures, :node_kind, :pkgs, :tags, :roles, :extra_config, :exception_handler, :exit_after_current_dispatch end - + self.signatures = {} self.node_kind = nil self.pkgs = [] @@ -16,7 +16,7 @@ class << self self.extra_config = nil self.exception_handler = nil self.exit_after_current_dispatch = false - + # Define a handler method # +method+ is the Symbol method name # +names+ is a list of required parameters @@ -24,17 +24,17 @@ class << self # Returns nothing def self.handle(method, *names, &block) Chassis.signatures[method] = names.sort { |a, b| a.to_s <=> b.to_s } - + define_method("handle_proxy_#{method}", &block) - + define_method("handle_#{method}".to_sym) do |iargs| args = self.convert_args(iargs) self.verify_args(method, args) - + self.send("handle_proxy_#{method}", args) end end - + # Specify this handler's kind # +name+ is a String identifier # @@ -42,21 +42,21 @@ def self.handle(method, *names, &block) def self.kind(name) Chassis.node_kind = name end - + # Specify details that will be used for matching incoming requests # +details+ is a Hash of primitives # # Returns nothing def self.details(details) raise("details() has already been called") unless Chassis.pkgs.empty? - + Chassis.pkgs = details.to_a end - + def self.config(&block) Chassis.extra_config = block.call end - + # Specify a block that takes an Exception as its single argument # to be called when an exception is not handled inside a handler # +block+ is the block to execute @@ -71,7 +71,7 @@ def self.config(&block) def self.handle_exception(&block) Chassis.exception_handler = block end - + # Limit version number to 9999 max # +version+ is the verstion number to limit # @@ -79,7 +79,7 @@ def self.handle_exception(&block) def self.limit_version(version) version.map { |x| x > 9999 ? 9999 : x } end - + # Convert Erlang-style args to Ruby-style args # +iargs+ is the Erlang-style arg structure # @@ -91,7 +91,7 @@ def convert_args(iargs) end args end - + # Helper for +convert_args+. Recursively converts a node in # Erlang-style to a node in Ruby-style # +node+ is the Erlang-style node @@ -99,7 +99,7 @@ def convert_args(iargs) # Returns String|Symbol|Hash|Array # Raises if an invalid node is encountered def convert_args_node(node) - if node.kind_of?(String) || node.kind_of?(Symbol) || node.kind_of?(Numeric) || + if node.kind_of?(String) || node.kind_of?(Symbol) || node.kind_of?(Numeric) || node.kind_of?(TrueClass) || node.kind_of?(FalseClass) || node.kind_of?(NilClass) node elsif node.instance_of?(Array) @@ -118,7 +118,7 @@ def convert_args_node(node) raise "Invalid node, must be an instance of String, Symbol, Numeric, True, False, Nil, or Array: #{node.inspect} (#{node.class.inspect})" end end - + # Verify that the required args are met for the given method call # +method+ is the Symbol representing the method name # +args+ is the Ruby-style args to check @@ -129,14 +129,14 @@ def verify_args(method, args) matches = Chassis.signatures[method].select do |key| args[key] end - + misses = Chassis.signatures[method] - matches - + unless misses.empty? raise "Required arguments missing for '#{method}': #{misses.join(", ")}" end end - + # Dispatch a method by its name # +method+ is the Symbol representing the method name # +retype+ is the response type Symbol (:json | :pure) @@ -169,7 +169,7 @@ def dispatch(method, retype, args) [:error, e.message + "\n\n" + e.backtrace.join("\n")] end end - + # The API structure of this Chassis, sorted alphabetically by method name # # Returns Array (Erlang-style nested structure) @@ -180,7 +180,7 @@ def api api = Chassis.signatures.to_a.sort { |a, b| a.first.to_s <=> b.first.to_s } api end - + # Construct the config (aka details) # # Returns Array (config) @@ -192,7 +192,7 @@ def config details << Chassis.extra_config if Chassis.extra_config details end - + # Start the Erlectricity recieve/respond loop # # Never returns @@ -206,32 +206,32 @@ def start exit if Chassis.exit_after_current_dispatch f.receive_loop end - + f.when(:config) do f.send! [:result, self.config] f.receive_loop end - + f.when(:api) do f.send! [:result, self.api] f.receive_loop end - + f.when(:ping) do f.send! :pong f.receive_loop end - + f.when(:quit) do exit(0) end end end - + def self.pull_cli_args Chassis.tags = [] Chassis.roles = [] - + # parse the options opts = OptionParser.new opts.on("--tags x,y,z", Array) do |val| @@ -241,44 +241,44 @@ def self.pull_cli_args Chassis.roles = val end opts.parse(ARGV) - + # grab the extras extras = [] dashdash = ARGV.index('--') if dashdash extras = ARGV[(dashdash + 1)..-1] end - + # ramrod the extras into ARGV ARGV.clear ARGV.concat(extras) end - + def self.start # get any handlers handlers = [] ObjectSpace.each_object(Class) do |o| handlers << o if o < Chassis end - + if $! raise $! end - + # check that one and only one exist if handlers.size != 1 raise "There must be exactly one class that extends Chassis, but there are #{handlers.size}" end - + # check that a kind has been set unless Chassis.node_kind raise "A kind must be specified" end - + h = handlers.first.new h.start end - + def return_and_exit(data) Chassis.exit_after_current_dispatch = true data @@ -391,178 +391,178 @@ def with_indifferent_access if $0 == __FILE__ require 'test/unit' require 'mocha' - + class Chassis def self.start nil end end - + class Awesome < Chassis kind "awesome" - + details "failboat" => "sinking" - + config do ["grammar", "/tmp/awesome.lfg"] end - + handle(:alpha) do 'alpha' end - + handle(:beta, :foo, :bar) do |args| helper(args[:foo], args[:bar]) end - + handle(:gamma) do raise "once more unto the breach" end - + handle(:delta) do exit end - + handle(:epsilon) do return_and_exit('foo') end - + handle_exception do |e| raise "EBORKD" end - + def helper(x, y) "#{x}=#{y}" end end - + class TestChassis < Test::Unit::TestCase def setup @a = Awesome.new end - + # signatures - + def test_signatures_should_match_declaration sigs = {:gamma=>[], :alpha=>[], :delta=>[], :beta=>[:bar, :foo], :epsilon=>[]} assert_equal sigs, Chassis.signatures end - + # handler meta - + def test_handler_methods_should_exist assert @a.respond_to?(:handle_alpha) assert @a.respond_to?(:handle_beta) end - + def test_handler_methods_arity_should_always_be_one assert 1, @a.method(:handle_alpha).arity assert 1, @a.method(:handle_beta).arity end - + # convert_args - + def test_convert_args_should_convert_top_level_array_to_hash i = [[:foo, 'bar'], [:qux, 'quux']] o = {'foo' => 'bar', 'qux' => 'quux'} assert_equal o, @a.convert_args(i) - + i = [['foo', 'bar'], ['qux', 'quux']] o = {'foo' => 'bar', 'qux' => 'quux'} assert_equal o, @a.convert_args(i) end - + def test_convert_args_should_convert_structs_to_indifferent_hashes i = [[:foo, 'bar'], [:baz, [:struct, [[:qux, 'quux']]]]] o = {'foo' => 'bar', 'baz' => {'qux' => 'quux'}} assert_equal o, @a.convert_args(i) - + i = [[:foo, 'bar'], [:baz, [:struct, [[:qux, [:struct, [[:a, 'b']]]]]]]] o = {'foo' => 'bar', 'baz' => {'qux' => {'a' => 'b'}}} assert_equal o, @a.convert_args(i) end - + def test_convert_args_should_make_all_hashes_indifferent i = [[:foo, 'bar'], [:baz, [:struct, [[:qux, 'quux']]]]] # o = {'foo' => 'bar', 'baz' => {'qux' => 'quux'}} o = @a.convert_args(i) assert_equal 'bar', o[:foo] assert_equal 'bar', o['foo'] - + assert_equal 'quux', o[:baz][:qux] assert_equal 'quux', o['baz']['qux'] end - + def test_convert_args_should_convert_arrays_to_arrays i = [[:foo, 'bar'], [:baz, [:array, [:qux, 'quux']]]] o = {'foo' => 'bar', 'baz' => [:qux, 'quux']} assert_equal o, @a.convert_args(i) - + i = [[:foo, 'bar'], [:baz, [:array, [:qux, [:array, [:a, 'b']]]]]] o = {'foo' => 'bar', 'baz' => [:qux, [:a, 'b']]} assert_equal o, @a.convert_args(i) end - + # convert_args_node - + def test_convert_node_should_be_identity_for_strings assert_equal 'foo', @a.convert_args_node('foo') end - + def test_convert_node_should_be_identity_for_symbol assert_equal :foo, @a.convert_args_node(:foo) end - + def test_convert_node_should_be_identity_for_true assert_equal true, @a.convert_args_node(true) end - + def test_convert_node_should_be_identity_for_false assert_equal false, @a.convert_args_node(false) end - + def test_convert_node_should_be_identity_for_nil assert_equal nil, @a.convert_args_node(nil) end - + def test_convert_node_should_be_identity_for_numeric assert_equal 1, @a.convert_args_node(1) assert_equal 1.0, @a.convert_args_node(1.0) assert_equal 9999999999999999999, @a.convert_args_node(9999999999999999999) end - + def test_convert_node_should_convert_array assert_equal [1], @a.convert_args_node([:array, [1]]) assert_equal [1, 2], @a.convert_args_node([:array, [1, 2]]) assert_equal [1, 2, 3], @a.convert_args_node([:array, [1, 2, 3]]) end - + def test_convert_node_should_convert_nested_array assert_equal [[1]], @a.convert_args_node([:array, [[:array, [1]]]]) end - + def test_convert_node_should_convert_struct_to_hash i = [:struct, [[:foo, 'foo']]] o = {"foo" => 'foo'} assert_equal o, @a.convert_args_node(i) end - + # handlers - + def test_alpha_nominal assert_equal 'alpha', @a.handle_alpha([]) end - + def test_beta_nominal assert_equal 'foo=bar', @a.handle_beta([[:foo, 'foo'], [:bar, 'bar']]) end - + def test_beta_with_missing_required_arg_should_raise assert_raise RuntimeError do @a.handle_beta([[:foo, 'foo']]) end end - + def test_epsilon_should_set_exit_after_current_dispatch assert_equal false, Chassis.exit_after_current_dispatch @a.dispatch(:epsilon, :json, []) @@ -572,7 +572,7 @@ def test_epsilon_should_set_exit_after_current_dispatch ensure Chassis.exit_after_current_dispatch = false end - + def test_epsilon_should_respond_with_last_result res = @a.dispatch(:epsilon, :json, []) assert_equal [:last_result, [:raw, "\"foo\""]], res @@ -581,64 +581,64 @@ def test_epsilon_should_respond_with_last_result ensure Chassis.exit_after_current_dispatch = false end - + # api - + def test_api assert_equal [[:alpha, []], [:beta, [:bar, :foo]], [:delta, []], [:epsilon, []], [:gamma, []]], @a.api end - + # kind - + def test_kind assert_equal "awesome", Chassis.node_kind end - + # packages - + def test_packages packages = [["failboat", "sinking"]] assert_equal packages, Chassis.pkgs end - + # handle_exception - + def test_handle_exception @a.dispatch(:gamma, :json, []) rescue => e assert_equal "EBORKD", e.message end - + # pull_cli_args - + def test_pull_cli_args ARGV.clear ARGV.concat(["--tags=foo,bar", "--", "--tags=baz,qux"]) - + Chassis.pull_cli_args - + assert_equal ["foo", "bar"], Chassis.tags assert_equal ["--tags=baz,qux"], ARGV end - + # config - + def test_config ARGV.clear ARGV.concat(["--tags=foo,bar", "--roles=production", "--", "--tags=baz,qux"]) Chassis.pull_cli_args - + config = [["failboat", "sinking"], ["tags", "foo", "bar"], ["roles", "production"], ["kind", "awesome"], ["grammar", "/tmp/awesome.lfg"]] - + assert_equal config, @a.config end - + # return_and_exit - + def test_return_and_exit assert_equal false, Chassis.exit_after_current_dispatch assert_equal 'foo', @a.return_and_exit('foo') diff --git a/rlibs/cli/boot.rb b/rlibs/cli/boot.rb index 218bf27..abf870c 100644 --- a/rlibs/cli/boot.rb +++ b/rlibs/cli/boot.rb @@ -9,7 +9,7 @@ def finish_spec(yml_spec, autoconf) yml_spec["master_host"] ||= autoconf.master_hostname yml_spec["master_node"] ||= autoconf.master_nodename yml_spec["heartbeat"] = false if yml_spec["heartbeat"].nil? - + return yml_spec end @@ -24,14 +24,14 @@ def client_spec_2_cmdline(yml_spec, autoconf) cmd_set << "-c " + yml_spec["clone"].to_s if yml_spec["clone"] cmd_set << "-s " + "'" + yml_spec["spec"] + "'" if yml_spec["spec"] cmd_set << "-h" if yml_spec["heartbeat"] - + return cmd_set.join(" ") end def read_directory_configs(path) names = [] configs = [] - + Dir.new(path).each do |f| if f =~ /\.yml$/i YAML::load(File.read(File.join(path, f))).each do |conf| @@ -43,7 +43,7 @@ def read_directory_configs(path) end end end - + configs end @@ -66,7 +66,7 @@ def read_configs(path) configs = read_configs(fuzed_bootpath) commands += configs.map {|x| client_spec_2_cmdline(x, environment)} commands.each {|x| puts x ; `#{x}` ; sleep(1) } -rescue +rescue puts "Failed to boot FUZED during configuration stage.\nError:#{$!}" puts $!.backtrace.join("\n") exit(1) diff --git a/rlibs/cli/console.rb b/rlibs/cli/console.rb index 3ae2575..d627f50 100644 --- a/rlibs/cli/console.rb +++ b/rlibs/cli/console.rb @@ -7,7 +7,7 @@ opts.on("-t", "--target TARGETNODE", "Node to target, defaults to your cluster's master or fuzed-dev") do |arg| options[:target] = arg end - + opts.on("-m", "--master TARGETNODE", "Master node for cookie generation. Defaults to your target.") do |arg| options[:master] = arg end diff --git a/rlibs/cli/frontend.rb b/rlibs/cli/frontend.rb index 974101b..dc56482 100644 --- a/rlibs/cli/frontend.rb +++ b/rlibs/cli/frontend.rb @@ -30,37 +30,37 @@ def purge(str) options = {} OptionParser.new do |opts| opts.banner = "Usage: fuzed command [options]" - + opts.on("-z HOSTNAME", "--magic HOSTNAME", "Set smart details based off of a hostname") do |n| options[:master_name] = "master@#{n}" end - + opts.on("-n NAME", "--name NAME", "Node name") do |n| options[:name] = n end - + opts.on("-m NAME", "--master NAME", "Master node name") do |n| options[:master_name] = n end - + opts.on("-s", "--spec SPECSTRING", "||-separated list of arguments to apply to your FUZED node") do |n| options[:spec] = n end - + opts.on("--server SERVER", "HTTP Server to use. Choices are: mochiweb, yaws") do |server| $stderr.puts "Unknown server type. Using yaws." unless %w[mochiweb yaws].include?(server) options[:http_server] = server end - + opts.on("--framework FRAMEWORK", "Framework to use. Choices are: rails") do |framework| $stderr.puts "Unknown framework type. Using rails." unless %w[framework].include?(framework) options[:framework] = framework end - + opts.on("--conf CONF", "Configuration file") do |conf| options[:conf] = conf end - + opts.on("-d", "--detached", "Run as a daemon") do options[:detached] = true end @@ -69,11 +69,11 @@ def purge(str) options[:docroot] = dir raise "No such directory for docroot!" unless File.directory?(dir) end - + opts.on("--ssl-key KEY", "SSL key file.") do |key| options[:ssl_key] = key end - + opts.on("--ssl-cert CERT", "SSL cert file.") do |cert| options[:ssl_cert] = cert end @@ -81,7 +81,7 @@ def purge(str) opts.on("-p", "--port PORT", "Port for web server.") do |dir| options[:port] = dir end - + opts.on("-P", "--pidfile PIDFILE", "Location to write pid file.") do |pidfile| options[:pidfile] = pidfile end diff --git a/rlibs/cli/join.rb b/rlibs/cli/join.rb index 710bef2..46aac72 100644 --- a/rlibs/cli/join.rb +++ b/rlibs/cli/join.rb @@ -22,47 +22,47 @@ def create_spec_list(options) options = {} OptionParser.new do |opts| opts.banner = "Usage: fuzed command [options]" - + opts.on("-z HOSTNAME", "--magic HOSTNAME", "Set smart details based off of a hostname") do |n| options[:master_name] = "master@#{n}" end - + opts.on("-n NAME", "--name NAME", "Node name") do |n| options[:name] = n end - + opts.on("-f FUZEDFILE", "--fuzedfile FILENAME", "FUZED spec file to use to serve nodes") do |n| options[:fuzedfile] = n end - + opts.on("-m NAME", "--master NAME", "Master node name") do |n| options[:master_name] = n end - + opts.on("-s", "--spec SPECSTRING", "||-separated list of arguments to apply to your FUZED node") do |n| options[:spec] = n end - + opts.on("-c NUMNODES", "--clone NUMTIMES", "Number of clones of your spec to make") do |n| options[:num_nodes] = n end - + opts.on("-t", "--tags TAGSTRING", "Comma-separated list of tags to apply to any nodes started") do |n| options[:tags] = n end - + opts.on("-d", "--detached", "Run as a daemon") do options[:detached] = true end - + opts.on("-p", "--production", "Classify these nodes as production") do options[:production] = true end - + opts.on("-r", "--roles ROLES", "Extra roles (use -p for production role)") do |v| options[:roles] = v end - + opts.on("-i", "--inet", "Load code over internet via master code server") do options[:inet] = true end @@ -71,7 +71,7 @@ def create_spec_list(options) $stderr.puts "WARNING! Heartbeats not supported with this build!" end end.parse! - + command = ARGV[0] detached = options[:detached] ? '-detached' : '' @@ -85,14 +85,14 @@ def create_spec_list(options) spec = %{[} + create_spec_list(options).map {|x| %{"#{x}"}}.join(",") + %{]} num_nodes = options[:num_nodes] || 1 -inet = +inet = if options[:inet] # Ruby has an awesome bug that makes me have to shell out to it, I'm not insane, I swear ip = `ruby -e "require 'resolv'; puts Resolv.getaddress('#{master.split('@').last}') rescue ''"`.chomp ip = `ruby -e "require 'resolv'; puts Resolv.getaddress('#{master.split('@').last.split('.').first}') rescue ''"`.chomp if ip == '' - + abort("Could not resolve #{master.split('@').last} to an IP address") unless ip - + " -loader inet -hosts '#{ip}'" else "" diff --git a/rlibs/cli/leave.rb b/rlibs/cli/leave.rb index a9f6fc2..f257279 100644 --- a/rlibs/cli/leave.rb +++ b/rlibs/cli/leave.rb @@ -1,12 +1,12 @@ options = {} OptionParser.new do |opts| opts.banner = "Usage: fuzed leave -n NAME" - + opts.on("-n NAME", "--name NAME", "Node name (hostname will automatically be appended)") do |n| options[:name] = n end end.parse! - + node = options[:name] + "@" + `hostname`.strip cmd = %Q{erl -noshell -name nodekiller -eval "rpc:call('#{node}', erlang, halt, []), halt()."} diff --git a/rlibs/cli/local.rb b/rlibs/cli/local.rb index 450950e..3675ebc 100644 --- a/rlibs/cli/local.rb +++ b/rlibs/cli/local.rb @@ -1,16 +1,16 @@ options = {} OptionParser.new do |opts| opts.banner = "Usage: fuzed local [options]" - + opts.on("-o NUMNODES", "--num_nodes NUMNODES", "Number of nodes to run") do |n| options[:num_nodes] = n end - + opts.on("-t", "--tags TAGSTRING", "Comma-separated list of tags to apply to any nodes started") do |n| options[:tags] = n end end.parse! - + command = ARGV[0] num_nodes = options[:num_nodes] diff --git a/rlibs/cli/publish.rb b/rlibs/cli/publish.rb index 772942f..7708147 100644 --- a/rlibs/cli/publish.rb +++ b/rlibs/cli/publish.rb @@ -4,7 +4,7 @@ options = {:master => :default} OptionParser.new do |opts| opts.banner = "Usage: fuzed publish [-m master]" - + opts.on("-m", "--master TARGETNODE", "Master node for cookie generation. Defaults to your target.") do |arg| options[:master] = arg end diff --git a/rlibs/cli/rails.rb b/rlibs/cli/rails.rb index 2da7005..af9eb13 100644 --- a/rlibs/cli/rails.rb +++ b/rlibs/cli/rails.rb @@ -22,47 +22,47 @@ def create_spec_list(options) OptionParser.new do |opts| opts.banner = "Usage: fuzed command [options]" - + opts.on("-z HOSTNAME", "--magic HOSTNAME", "Set smart details based off of a hostname") do |n| options[:master_name] = "master@#{n}" end - + opts.on("-n NAME", "--name NAME", "Node name") do |n| options[:name] = n end - + opts.on("-m NAME", "--master NAME", "Master node name") do |n| options[:master_name] = n end - + opts.on("--rails-root RAILS_ROOT", "Location of the Rails root") do |n| options[:spec] << "--rails-root=#{n}" end - + opts.on("--rails-env RAILS_ENV", "Rails environment (default 'development')") do |n| options[:spec] << "--rails-env=#{n}" end - + opts.on("-c NUMNODES", "--clone NUMTIMES", "Number of clones of your spec to make") do |n| options[:num_nodes] = n end - + opts.on("-t", "--tags TAGSTRING", "Comma-separated list of tags to apply to any nodes started") do |n| options[:tags] = n end - + opts.on("-d", "--detached", "Run as a daemon") do options[:detached] = true end - + opts.on("-p", "--production", "Classify these nodes as production") do options[:production] = true end - + opts.on("-r", "--roles ROLES", "Extra roles (use -p for production role)") do |v| options[:roles] = v end - + opts.on("-i", "--inet", "Load code over internet via master code server") do options[:inet] = true end @@ -71,7 +71,7 @@ def create_spec_list(options) $stderr.puts "WARNING! Heartbeats not supported with this build!" end end.parse! - + command = ARGV[0] detached = options[:detached] ? '-detached' : '' @@ -85,14 +85,14 @@ def create_spec_list(options) spec = %{[} + create_spec_list(options).map {|x| %{"#{x}"}}.join(",") + %{]} num_nodes = options[:num_nodes] || 1 -inet = +inet = if options[:inet] # Ruby has an awesome bug that makes me have to shell out to it, I'm not insane, I swear ip = `ruby -e "require 'resolv'; puts Resolv.getaddress('#{master.split('@').last}') rescue ''"`.chomp ip = `ruby -e "require 'resolv'; puts Resolv.getaddress('#{master.split('@').last.split('.').first}') rescue ''"`.chomp if ip == '' - + abort("Could not resolve #{master.split('@').last} to an IP address") unless ip - + " -loader inet -hosts '#{ip}'" else "" diff --git a/rlibs/cli/start.rb b/rlibs/cli/start.rb index 71224e6..e275b37 100644 --- a/rlibs/cli/start.rb +++ b/rlibs/cli/start.rb @@ -3,11 +3,11 @@ options = {} OptionParser.new do |opts| opts.banner = "Usage: fuzed start [options]" - + opts.on("-n NAME", "--name NAME", "Node name") do |n| options[:name] = n end - + opts.on("--server SERVER", "HTTP Server to use. Choices are: mochiweb, yaws") do |server| $stderr.puts "Unknown server type. Using yaws." unless %w[mochiweb yaws].include?(server) options[:http_server] = server @@ -16,12 +16,12 @@ opts.on("-d", "--detached", "Run as a daemon") do options[:detached] = true end - + opts.on("-h", "--heartbeat", "Start with a heartbeat.") do $stderr.puts "WARNING! Heartbeats not supported with this build!" end end.parse! - + command = ARGV[0] detached = options[:detached] ? '-detached' : '' diff --git a/rlibs/cli/status.rb b/rlibs/cli/status.rb index a6dcc95..4348bdd 100644 --- a/rlibs/cli/status.rb +++ b/rlibs/cli/status.rb @@ -1,7 +1,7 @@ -# --- +# --- # port: 9001 # host: localhost -# specs: +# specs: # - foo/2 # - bar/4 @@ -12,7 +12,7 @@ options = {:host => :auto, :port => 9001, :spec => []} OptionParser.new do |opts| opts.banner = "Usage: fuzed status [options]" - + opts.on("-c CONFIG", "--config CONFIG", "Configuration file") do |x| contents = File.read(x) data = YAML.load(contents) @@ -20,15 +20,15 @@ options[:port] = data['port'] if data['port'] options[:spec] += data['specs'] if data['specs'] end - + opts.on("-h HOST", "--host HOST", "Hostname. Default: localhost") do |x| options[:host] = x end - + opts.on("-p PORT", "--port PORT", "Port. Default: 9001") do |x| options[:port] = x end - + opts.on("-s SPEC", "--spec SPEC", "Specify a kind/number to check on") do |n| options[:spec] << n end diff --git a/rlibs/cli/unpublish.rb b/rlibs/cli/unpublish.rb index edc30f9..672b9bd 100644 --- a/rlibs/cli/unpublish.rb +++ b/rlibs/cli/unpublish.rb @@ -4,7 +4,7 @@ options = {:master => :default} OptionParser.new do |opts| opts.banner = "Usage: fuzed publish [-m master]" - + opts.on("-m", "--master TARGETNODE", "Master node for cookie generation. Defaults to your target.") do |arg| options[:master] = arg end diff --git a/rlibs/cli/upgrade.rb b/rlibs/cli/upgrade.rb index e19c362..5d4b148 100644 --- a/rlibs/cli/upgrade.rb +++ b/rlibs/cli/upgrade.rb @@ -2,24 +2,24 @@ OptionParser.new do |opts| opts.banner = "Usage: fuzed upgrade [options]" - + opts.on("-n NAME", "--name NAME", "Node name") do |n| options[:name] = n end - + opts.on("-m NAME", "--master NAME", "Master node name") do |n| options[:master_name] = n end - + opts.on("-r", "--ruby_only", "Only reload Ruby segment") do |n| options[:kind] = :ruby end - + opts.on("-e", "--erlang_only", "Only reload Erlang segment") do |n| options[:kind] = :erlang end end.parse! - + command = ARGV[0] name = options[:name] diff --git a/rlibs/fake_node.rb b/rlibs/fake_node.rb index 2f8c5fc..e11c5f5 100644 --- a/rlibs/fake_node.rb +++ b/rlibs/fake_node.rb @@ -11,7 +11,7 @@ class FakeHandler < Chassis handle(:echo, :textsy, :options) do |args| "You said: " + args[:textsy] + ' ' + args[:options].inspect end - + handle(:killer) do |args| exit end @@ -19,7 +19,7 @@ class FakeHandler < Chassis handle(:woot) do |args| "Boots are delightful." end - + handle(:mangler) do |args| return_and_exit("Let slip the dogs of war") end diff --git a/rlibs/fuzed_handler.rb b/rlibs/fuzed_handler.rb index dd98dcf..fee962d 100644 --- a/rlibs/fuzed_handler.rb +++ b/rlibs/fuzed_handler.rb @@ -27,11 +27,11 @@ def initialize(app, logfile) @app = app $logger = Logger.new(logfile) if LOG end - + def service(request) log('------------RAW IN------------') if LOG log(request.inspect) if LOG - + method = request['method'] version = request['http_version'] # => e.g. [1, 1] remote_addr = request['remote_addr'] @@ -41,7 +41,7 @@ def service(request) headers = request['headers'] cookies = request['cookies'] postdata = request['postdata'] == :undefined ? '' : request['postdata'] - + translate = {'content_type' => 'CONTENT_TYPE', 'content_length' => 'CONTENT_LENGTH', 'authorization' => 'HTTP_AUTHORIZATION', @@ -57,7 +57,7 @@ def service(request) 'X-Prototype-Version' => 'HTTP_X_PROTOTYPE_VERSION', 'X-Requested-With' => 'HTTP_X_REQUESTED_WITH', 'X-Forwarded-Proto' => 'HTTP_X_FORWARDED_PROTO'} - + env = {} env['REQUEST_METHOD'] = method.to_s env['REMOTE_ADDR'] = remote_addr @@ -65,77 +65,77 @@ def service(request) env["PATH_INFO"] = path env = headers.inject(env) { |a, x| a[translate[x[0]] || x[0].to_s] = x[1]; a } env.delete_if { |k, v| v.nil? } - + env.update({"rack.version" => [0, 1], "rack.input" => StringIO.new(postdata), "rack.errors" => STDERR, - + "rack.multithread" => true, "rack.multiprocess" => false, "rack.run_once" => false, - + "rack.url_scheme" => request['https'] == 1 ? "https" : "http" }) - + env['SERVER_NAME'] = server.split(':')[0] env['SERVER_PORT'] = server.split(':')[1] env['HTTP_VERSION'] = version.join('.') env['HTTPS'] = request['https'] == 1 ? "on" : "off" - + env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["QUERY_STRING"] ||= "" env["REQUEST_PATH"] ||= "/" env.delete "PATH_INFO" if env["PATH_INFO"] == "" - + cookies.each do |cookie| env["HTTP_COOKIE"] = cookie.to_s end - + log('------------IN------------') if LOG log(env.inspect) if LOG - + begin t1 = Time.now - + status, headers, body = @app.call(env) - + rails_delta = Time.now - t1 $rails_avg[0] += rails_delta $rails_avg[1] += 1 log(">> Rails in #{rails_delta} (#{$rails_avg[0] / $rails_avg[1]} avg) sec") if LOG - + html = '' body.each do |part| html << part end - + headers['Server'] = 'YAWS + Fuzed 0.0.1' headers['Connection'] = 'close' - + cookies = headers.delete('cookie') headers['Set-Cookie'] = cookies if cookies - + status = (headers["Status"].split(" ").first rescue nil) || status headers.delete("Status") if headers["Status"] - res = + res = [:response, [[:status, status.to_i], [:allheaders, headers.keys.inject([]) {|x,y| x << [:header, y, headers[y]]}], [:html, html]]] rescue => e - res = - [:response, + res = + [:response, [[:status, 500], [:allheaders, [ - [:header, "Content-Type", "text/plain; charset=utf-8"], - [:header, "Cache-Control", "no-cache"]]], + [:header, "Content-Type", "text/plain; charset=utf-8"], + [:header, "Cache-Control", "no-cache"]]], [:html, "500 Internal Error\n\n#{e}\n\n#{e.backtrace}"]]] end - + log('-----------OUT------------') if LOG log(res.inspect) if LOG - + res end end diff --git a/rlibs/json_client.rb b/rlibs/json_client.rb index a00183f..0af6935 100644 --- a/rlibs/json_client.rb +++ b/rlibs/json_client.rb @@ -11,40 +11,40 @@ def initialize(uri, prefix='') raise "need a legitimate URI" unless @uri.host @prefix = prefix end - + # can use symbols for arg names if you want def call(methodname, arghash={}) arghash.is_a?(Hash) or raise "must pass hash args" - + envelope = { 'method' => methodname, 'params' => arghash } - + puts '--------------------' puts envelope.to_json puts '--------------------' - + body = Net::HTTP.new(@uri.host, @uri.port).post(@uri.path, envelope.to_json, {'Content-Type' => 'application/json'}).body jr = JSON.parse(body) || {} rescue {} - + puts '--------------------' puts body puts '--------------------' - + if jr['error'] # some lazy jsonrpc implementations just have a string here raise JSONRPCError, jr['error'].to_s if !jr['error'].is_a?(Hash) - + e = JSONRPCError.new(jr['error']['message']) e.code = jr['error']['code'] e.error = jr['error']['error'] raise e end - + return jr['result'] || "JSON parse error... (#{body})" end - + def method_missing(m, *a) if a.size == 0 && @prefix.empty? # then a prefix thingy, only 1 level of chaining self.new(@uri, m.to_s) @@ -56,11 +56,11 @@ def method_missing(m, *a) end end end - + class JSONRPCError < StandardError # numeric code attr_accessor :code - + # arbitrary json object attr_accessor :error end diff --git a/rlibs/rails_adapter.rb b/rlibs/rails_adapter.rb index 11e95ba..de916a4 100644 --- a/rlibs/rails_adapter.rb +++ b/rlibs/rails_adapter.rb @@ -14,56 +14,56 @@ # Based on http://fuzed.rubyforge.org/ Rails adapter # the circle is now complete! module Rack - module Adapter + module Adapter class Rails FILE_METHODS = %w(GET HEAD).freeze - + def initialize(options={}) @root = options[:root] || Dir.pwd @env = options[:environment] || 'development' @prefix = options[:prefix] - + load_application - + @file_server = Rack::File.new(::File.join(RAILS_ROOT, "public")) end - + def load_application ENV['RAILS_ENV'] = @env require "#{@root}/config/environment" require 'dispatcher' - - ActionController::AbstractRequest.relative_url_root = @prefix if @prefix + + ActionController::AbstractRequest.relative_url_root = @prefix if @prefix end - + # TODO refactor this in File#can_serve?(path) ?? def file_exist?(path) full_path = ::File.join(@file_server.root, Utils.unescape(path)) ::File.file?(full_path) && ::File.readable?(full_path) end - + def serve_file(env) @file_server.call(env) end - + def serve_rails(env) request = Request.new(env) response = Response.new - + session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS cgi = CGIWrapper.new(request, response) - + Dispatcher.dispatch(cgi, session_options, response) response.finish end - + def call(env) path = env['PATH_INFO'].chomp('/') method = env['REQUEST_METHOD'] cached_path = (path.empty? ? 'index' : path) + ActionController::Base.page_cache_extension - + if FILE_METHODS.include?(method) if file_exist?(path) # Serve the file if it's there return serve_file(env) @@ -72,13 +72,13 @@ def call(env) return serve_file(env) end end - + # No static file, let Rails handle it serve_rails(env) end - + protected - + class CGIWrapper < ::CGI def initialize(request, response, *args) @request = request @@ -88,72 +88,72 @@ def initialize(request, response, *args) super *args end - + def header(options = "text/html") if options.is_a?(String) @response['Content-Type'] = options unless @response['Content-Type'] else @response['Content-Length'] = options.delete('Content-Length').to_s if options['Content-Length'] - + @response['Content-Type'] = options.delete('type') || "text/html" @response['Content-Type'] += "; charset=" + options.delete('charset') if options['charset'] - + @response['Content-Language'] = options.delete('language') if options['language'] @response['Expires'] = options.delete('expires') if options['expires'] @response.status = options.delete('Status') if options['Status'] - + # Convert 'cookie' header to 'Set-Cookie' headers. - # Because Set-Cookie header can appear more the once in the response body, + # Because Set-Cookie header can appear more the once in the response body, # we store it in a line break seperated string that will be translated to # multiple Set-Cookie header by the handler. if cookie = options.delete('cookie') cookies = [] - + case cookie when Array then cookie.each { |c| cookies << c.to_s } when Hash then cookie.each { |_, c| cookies << c.to_s } else cookies << cookie.to_s end - + @output_cookies.each { |c| cookies << c.to_s } if @output_cookies - + @response['Set-Cookie'] = [@response['Set-Cookie'], cookies].compact.join("\n") end - + options.each { |k,v| @response[k] = v } end - + "" end - + def params @params ||= @request.params end - + def cookies @request.cookies end - + def query_string @request.query_string end - + # Used to wrap the normal args variable used inside CGI. def args @args end - + # Used to wrap the normal env_table variable used inside CGI. def env_table @request.env end - + # Used to wrap the normal stdinput variable used inside CGI. def stdinput @input end - + def stdoutput STDERR.puts "stdoutput should not be used." @response.body diff --git a/rlibs/rails_node.rb b/rlibs/rails_node.rb index 0a38db7..8ebbf65 100644 --- a/rlibs/rails_node.rb +++ b/rlibs/rails_node.rb @@ -11,10 +11,10 @@ # read command line options options = {} opts = OptionParser.new do |opts| - opts.on("-r", "--rails-root RAILS_ROOT", String) do |x| + opts.on("-r", "--rails-root RAILS_ROOT", String) do |x| options[:rails_root] = x end - opts.on("-t", "--test", "enable test mode") do + opts.on("-t", "--test", "enable test mode") do options[:test] = true end opts.on("-e", "--rails-env ENV", String) do |x| @@ -40,15 +40,15 @@ class RailsHandler < Chassis end # test mode -if options[:test] - req = - {:method => :POST, - :http_version => [1, 1], - :querypath => "/main/go", - :querydata => "", - :servername => "testing:8002", +if options[:test] + req = + {:method => :POST, + :http_version => [1, 1], + :querypath => "/main/go", + :querydata => "", + :servername => "testing:8002", :headers => {:connection => "keep-alive", - :accept => "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", + :accept => "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", :host => "localhost:8002", :referer => "http://localhost:8002/main/ready", :user_agent => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3", @@ -62,7 +62,7 @@ class RailsHandler < Chassis :cookies => ["_helloworld_session_id=d3eae987aab3230377abc433b7a8d7c1"], :pathinfo => "/Users/tom/dev/fuzed/helloworld/public", :postdata => "val=foo"} - + p $handler.service(req) exit! end \ No newline at end of file diff --git a/rtest/test_cli_boot.rb b/rtest/test_cli_boot.rb index e98250b..2ae91ce 100644 --- a/rtest/test_cli_boot.rb +++ b/rtest/test_cli_boot.rb @@ -8,26 +8,26 @@ class TestCliBoot < Test::Unit::TestCase def test_default_config ARGV.clear ARGV << '' << File.join(File.dirname(__FILE__), *%w[fixtures boot default.yml]) - + FUZEDAutoConfig.expects(:new).returns(stub(:is_master? => false, :master_hostname => 'aa0-foo', :master_nodename => 'master')) - + Object.any_instance.expects(:`).times(2) - + load 'cli/boot.rb' end - + def test_dir_config ARGV.clear ARGV << '' << File.join(File.dirname(__FILE__), *%w[fixtures boot configs]) - + FUZEDAutoConfig.expects(:new).returns(stub(:is_master? => false, :master_hostname => 'aa0-foo', :master_nodename => 'master')) - + Object.any_instance.expects(:`).times(3) - + load 'cli/boot.rb' end end \ No newline at end of file diff --git a/test/app/app/controllers/application.rb b/test/app/app/controllers/application.rb index 7a166b4..d83a5e8 100644 --- a/test/app/app/controllers/application.rb +++ b/test/app/app/controllers/application.rb @@ -4,6 +4,6 @@ class ApplicationController < ActionController::Base # Pick a unique cookie name to distinguish our session data from others' session :session_key => '_helloworld_session_id' - + session :off end diff --git a/test/app/app/controllers/main_controller.rb b/test/app/app/controllers/main_controller.rb index 0f1ed92..ea5684b 100644 --- a/test/app/app/controllers/main_controller.rb +++ b/test/app/app/controllers/main_controller.rb @@ -4,47 +4,47 @@ class MainController < ApplicationController before_filter :authenticate, :only => :ssl def index - + end - + def say render :text => "hello world - #{session[:time]}" end - + def set session[:time] = Time.now.to_s render :text => 'done' end - + def chronic s = Chronic.parse(params[:id]) render :text => s ? s.strftime('%d %b %Y @ %I:%M.%S %p') : '...' end - + def ready - + end - + def go render :text => 'done' end - + def hog loop { } end - + def ssl render :text => request.ssl?.to_s end - + def ip render :text => request.remote_ip.to_s end - + def fail raise "failboat" end - + protected def authenticate diff --git a/test/app/app/views/main/index.rhtml b/test/app/app/views/main/index.rhtml index 0cc7406..0675d98 100644 --- a/test/app/app/views/main/index.rhtml +++ b/test/app/app/views/main/index.rhtml @@ -5,7 +5,7 @@

...