2222-module (basho_bench ).
2323
2424-export ([main /1 , md5 /1 ]).
25-
2625-include (" basho_bench.hrl" ).
2726
2827% % ====================================================================
@@ -53,6 +52,8 @@ main(Args) ->
5352 {error , {already_loaded , basho_bench }} -> ok
5453 end ,
5554 register (basho_bench , self ()),
55+ % % TODO: Move into a proper supervision tree, janky for now
56+ {ok , _Pid } = basho_bench_config :start_link (),
5657 basho_bench_config :set (test_id , BenchName ),
5758
5859 application :load (lager ),
@@ -93,15 +94,16 @@ main(Args) ->
9394 % % Copy the config into the test dir for posterity
9495 [ begin {ok , _ } = file :copy (Config , filename :join (TestDir , filename :basename (Config ))) end
9596 || Config <- Configs ],
96-
97+ case basho_bench_config :get (distribute_work , false ) of
98+ true -> setup_distributed_work ();
99+ false -> ok
100+ end ,
97101 % % Set our CWD to the test dir
98102 ok = file :set_cwd (TestDir ),
99-
100103 log_dimensions (),
101104
102105 % % Run pre_hook for user code preconditions
103106 run_pre_hook (),
104-
105107 % % Spin up the application
106108 ok = basho_bench_app :start (),
107109
@@ -139,6 +141,7 @@ maybe_net_node(Opts) ->
139141 case lists :keyfind (net_node , 1 , Opts ) of
140142 {_ , Node } ->
141143 {_ , Cookie } = lists :keyfind (net_cookie , 1 , Opts ),
144+ os :cmd (" epmd -daemon" ),
142145 net_kernel :start ([Node , longnames ]),
143146 erlang :set_cookie (Node , Cookie ),
144147 ok ;
@@ -256,6 +259,7 @@ load_source_files(Dir) ->
256259 case compile :file (F , [report , binary ]) of
257260 {ok , Mod , Bin } ->
258261 {module , Mod } = code :load_binary (Mod , F , Bin ),
262+ deploy_module (Mod ),
259263 ? INFO (" Loaded ~p (~s )\n " , [Mod , F ]),
260264 ok ;
261265 Error ->
@@ -276,6 +280,70 @@ run_hook({Module, Function}) ->
276280run_hook (no_op ) ->
277281 no_op .
278282
283+ get_addr_args () ->
284+ {ok , IfAddrs } = inet :getifaddrs (),
285+ FlattAttrib = lists :flatten ([IfAttrib || {_Ifname , IfAttrib } <- IfAddrs ]),
286+ Addrs = proplists :get_all_values (addr , FlattAttrib ),
287+ % If inet:ntoa is unavailable, it probably means that you're running <R16
288+ StrAddrs = [inet :ntoa (Addr ) || Addr <- Addrs ],
289+ string :join (StrAddrs , " " ).
290+ setup_distributed_work () ->
291+ case node () of
292+ 'nonode@nohost' ->
293+ ? STD_ERR (" Basho bench not started in distributed mode, and distribute_work = true~n " , []),
294+ halt (1 );
295+ _ -> ok
296+ end ,
297+ {ok , _Pid } = erl_boot_server :start ([]),
298+ % % Allow anyone to boot from me...I might want to lock this down this down at some point
299+ erl_boot_server :add_subnet ({0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 }),
300+ % % This is cheating, horribly, but it's the only simple way to bypass net_adm:host_file()
301+ gen_server :start ({global , pool_master }, pool , [], []),
302+ RemoteSpec = basho_bench_config :get (remote_nodes , []),
303+ Cookie = lists :flatten (erlang :atom_to_list (erlang :get_cookie ())),
304+ Args = " -setcookie " ++ Cookie ++ " -loader inet -hosts " ++ get_addr_args (),
305+ Slaves = [ slave :start_link (Host , Name , Args ) || {Host , Name } <- RemoteSpec ],
306+ SlaveNames = [SlaveName || {ok , SlaveName } <- Slaves ],
307+ [pool :attach (SlaveName ) || SlaveName <- SlaveNames ],
308+ CodePaths = code :get_path (),
309+ rpc :multicall (SlaveNames , code , set_path , [CodePaths ]),
310+ Apps = [lager , basho_bench , getopt , bear , folsom , ibrowse , riakc , riak_pb , mochiweb , protobuffs , velvet , goldrush ],
311+ [distribute_app (App ) || App <- Apps ].
312+
313+
314+ deploy_module (Module ) ->
315+ case basho_bench_config :get (distribute_work , false ) of
316+ true ->
317+ Nodes = nodes (),
318+ {Module , Binary , Filename } = code :get_object_code (Module ),
319+ rpc :multicall (Nodes , code , load_binary , [Module , Filename , Binary ]);
320+ false -> ok
321+ end .
322+
323+ distribute_app (App ) ->
324+ % :(. This is super hackish, it depends on a bunch of assumptions
325+ % But, unfortunately there are negative interactions with escript and slave nodes
326+ CodeExtension = code :objfile_extension (),
327+ LibDir = code :lib_dir (App ),
328+ % Get what paths are in the code path that start with LibDir
329+ LibDirLen = string :len (LibDir ),
330+ EbinsDir = lists :filter (fun (CodePathDir ) -> string :substr (CodePathDir , 1 , LibDirLen ) == LibDir end , code :get_path ()),
331+ StripEndFun = fun (Path ) ->
332+ PathLen = string :len (Path ),
333+ case string :substr (Path , PathLen - string :len (CodeExtension ) + 1 , string :len (Path )) of
334+ CodeExtension ->
335+ {true , string :substr (Path , 1 , PathLen - string :len (CodeExtension ))};
336+ _ -> false
337+ end
338+ end ,
339+ EbinDirDistributeFun = fun (EbinDir ) ->
340+ {ok , Beams } = erl_prim_loader :list_dir (EbinDir ),
341+ Modules = lists :filtermap (StripEndFun , Beams ),
342+ ModulesLoaded = [code :load_abs (filename :join (EbinDir , ModFileName )) || ModFileName <- Modules ],
343+ lists :foreach (fun ({module , Module }) -> deploy_module (Module ) end , ModulesLoaded )
344+ end ,
345+ lists :foreach (EbinDirDistributeFun , EbinsDir ),
346+ ok .
279347% % just a utility, should be in basho_bench_utils.erl
280348% % but 's' is for multiple utilities, and so far this
281349% % is the only one.
0 commit comments