7 VALID_STATES = [:init, :up, :start, :restart]
10 attr_accessor :state, :interval, :group,
11 :grace, :start_grace, :stop_grace, :restart_grace
14 attr_writer :autostart
15 def autostart?; @autostart; end
18 def_delegators :@process, :name, :uid, :gid, :start, :stop, :restart,
19 :name=, :uid=, :gid=, :start=, :stop=, :restart=
22 attr_accessor :behaviors, :metrics
28 def initialize(meddle)
30 @process = God::Process.new
34 # no grace period by default
35 self.grace = self.start_grace = self.stop_grace = self.restart_grace = 0
37 # the list of behaviors
40 # the list of conditions for each action
41 self.metrics = {:init => [],
47 self.mutex = Mutex.new
53 b = Behavior.generate(kind)
54 rescue NoSuchBehaviorError => e
58 # send to block so config can set attributes
59 yield(b) if block_given?
61 # abort if the Behavior is invalid, the Behavior will have printed
62 # out its own error messages by now
68 ###########################################################################
72 ###########################################################################
74 # Define a transition handler which consists of a set of conditions
75 def transition(start_states, end_states)
76 # convert to into canonical hash form
77 canonical_end_states = canonical_hash_form(end_states)
79 # for each start state do
80 Array(start_states).each do |start_state|
81 # validate start state
82 unless VALID_STATES.include?(start_state)
83 abort "Invalid state :#{start_state}. Must be one of the symbols #{VALID_STATES.map{|x| ":#{x}"}.join(', ')}"
86 # create a new metric to hold the watch, end states, and conditions
87 m = Metric.new(self, canonical_end_states)
89 # let the config file define some conditions on the metric
93 self.metrics[start_state] << m
97 ###########################################################################
101 ###########################################################################
104 self.transition(:up, :start) do |on|
110 self.transition(:up, :restart) do |on|
115 ###########################################################################
119 ###########################################################################
123 # start monitoring at the first available of the init or up states
124 if !self.metrics[:init].empty?
136 # Move from one state to another
138 msg = "move '#{self.state}' to '#{to_state}'"
142 # cleanup from current state
143 if from_state = self.state
144 self.metrics[from_state].each { |m| m.disable }
147 # perform action (if available)
148 self.action(to_state)
152 self.metrics[to_state].each { |m| m.enable }
156 self.state = to_state
162 def action(a, c = nil)
165 Syslog.debug(self.start)
167 call_action(c, :start)
168 sleep(self.start_grace + self.grace)
171 Syslog.debug(self.restart)
173 call_action(c, :restart)
178 sleep(self.restart_grace + self.grace)
180 Syslog.debug(self.stop)
182 call_action(c, :stop)
183 sleep(self.stop_grace + self.grace)
187 def call_action(condition, action)
189 before_items = self.behaviors
190 before_items += [condition] if condition
191 before_items.each { |b| b.send("before_#{action}") }
193 @process.call_action(action)
196 after_items = self.behaviors
197 after_items += [condition] if condition
198 after_items.each { |b| b.send("after_#{action}") }
201 def canonical_hash_form(to)
202 to.instance_of?(Symbol) ? {true => to} : to
206 God.registry.add @process