# Author:: Nicolas Pouillard . # Copyright:: Copyright (c) 2005 TTK Team. All rights reserved. # License:: LGPL # Revision:: $Id: /w/fey/uttk/trunk/lib/uttk/strategies/HostSelector.rb 29680 2006-09-13T07:36:54.996888Z ertai $ module Uttk module Strategies # # Example: # root: !S::Suite # contents: # - selector: !S::HostSelector # hosts: # The list of hosts. # - ssh://joe:tux@foo.com # Via ssh on foo.com. # - druby://bar.fr:4242/ttk # Another custom protocol. # - ... # Hosts can also be specified # # with a file containing hosts # # or an url. # static_select: | # Performed just one time. # reject! { |x| not x.alive? } # Example of static cleaning. # shuffle! # Shuffle the hosts. # dynamic_select: | # Called to elect an host. # roll # Move the first host to the # # end of the list and return it # # Other examples: # # - first (take the first) # # - choose (randomly) # - big suite: !S::Pool # attribute: !S::Jump # to: !url <> # test: !S::Suite # ... something long ... # contents: # - ... # - ... # class HostSelector < Strategy include Concrete # # Methods # def elect_host do_dynamic_select end def call ( selector, argument ) if selector.arity == 1 selector[argument] else argument.instance_eval(&selector) end end protected :call def do_static_select @hosts_pool = @hosts.dup result = call(@static_select, @hosts_pool) @hosts_pool = result unless result.nil? end protected :do_static_select def do_dynamic_select call(@dynamic_select, @hosts_pool) end protected :do_dynamic_select # # Suppose that we have URI::Generic#load_average which returns the current # load average of the targeted host. # # With dynamic select you can simply do that # # dynamic_select: # min { |x, y| x.load_average <=> y.load_average } # # dynamic_min: # load_average # # dynamic_min: # ((alive?)? 0 : Float::MAX) + 3 * load_average.first + 5 * current_jobs_count def do_dynamic_min @hosts_pool.min { |x, y| call(dynamic_min, x) <=> call(dynamic_min, y) } end protected :do_dynamic_min def prologue super @static_select = @static_select.to_proc @dynamic_select = @dynamic_select.to_proc if @dynamic_select @dynamic_min = @dynamic_min.to_proc if @dynamic_min unless @dynamic_select or @dynamic_min raise ArgumentError, "Need at least dynamic_select or dynamic_min" end @symtbl[:host_selector] = self @symtbl[:'host_selector.elect'] = SymTbl::Trigger.new { elect } # ... end protected :prologue def run_impl do_static_select # ... super # ... end protected :run_impl def assertion pass # ... super end protected :assertion def epilogue # ... super end protected :epilogue # # Attributes # attribute :hosts, 'hosts to distribute', Object, [], :mandatory attribute :static_select, 'static block for selection (called once)', [String, Proc], 'shuffle' attribute :dynamic_select, 'dynamic block for selection (called for each election)', [String, Proc], 'roll' end # class HostSelector end # module Strategies end # module Uttk