4 VALID_STATES = [:init, :up, :start, :restart]
7 attr_accessor :name, :state, :start, :stop, :restart, :interval, :grace
10 attr_accessor :behaviors, :metrics
16 def initialize(meddle)
19 # no grace period by default
22 # the list of behaviors
25 # the list of conditions for each action
26 self.metrics = {:init => [],
32 self.mutex = Mutex.new
38 b = Behavior.generate(kind)
39 rescue NoSuchBehaviorError => e
43 # send to block so config can set attributes
44 yield(b) if block_given?
46 # abort if the Behavior is invalid, the Behavior will have printed
47 # out its own error messages by now
53 ###########################################################################
57 ###########################################################################
59 # Define a transition handler which consists of a set of conditions
60 def transition(start_states, end_states)
61 # convert to into canonical hash form
62 canonical_end_states = canonical_hash_form(end_states)
64 # for each start state do
65 Array(start_states).each do |start_state|
66 # validate start state
67 unless VALID_STATES.include?(start_state)
68 abort "Invalid state :#{start_state}. Must be one of the symbols #{VALID_STATES.map{|x| ":#{x}"}.join(', ')}"
71 # create a new metric to hold the watch, end states, and conditions
72 m = Metric.new(self, canonical_end_states)
74 # let the config file define some conditions on the metric
78 self.metrics[start_state] << m
82 ###########################################################################
86 ###########################################################################
89 self.transition(:up, :start) do |on|
95 self.transition(:up, :restart) do |on|
100 ###########################################################################
104 ###########################################################################
106 # Schedule all poll conditions and register all condition events
108 # start monitoring at the init state
112 # Move from one state to another
114 puts "move '#{self.state}' to '#{to_state}'"
116 # cleanup from current state
117 if from_state = self.state
118 self.metrics[from_state].each { |m| m.disable }
121 # perform action (if available)
122 self.action(to_state)
125 self.metrics[to_state].each { |m| m.enable }
128 self.state = to_state
131 def action(a, c = nil)
135 call_action(c, :start, self.start)
140 call_action(c, :restart, self.restart)
148 call_action(c, :stop, self.stop)
153 def call_action(condition, action, command)
155 before_items = self.behaviors
156 before_items += [condition] if condition
157 before_items.each { |b| b.send("before_#{action}") }
160 if command.kind_of?(String)
169 after_items = self.behaviors
170 after_items += [condition] if condition
171 after_items.each { |b| b.send("after_#{action}") }
174 def canonical_hash_form(to)
175 to.instance_of?(Symbol) ? {true => to} : to