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=,
23 attr_accessor :behaviors, :metrics
31 @process = God::Process.new
33 # no grace period by default
34 self.grace = self.start_grace = self.stop_grace = self.restart_grace = 0
36 # the list of behaviors
39 # the list of conditions for each action
40 self.metrics = {:init => [],
46 self.mutex = Mutex.new
52 b = Behavior.generate(kind, self)
53 rescue NoSuchBehaviorError => e
57 # send to block so config can set attributes
58 yield(b) if block_given?
60 # abort if the Behavior is invalid, the Behavior will have printed
61 # out its own error messages by now
67 ###########################################################################
71 ###########################################################################
73 # Define a transition handler which consists of a set of conditions
74 def transition(start_states, end_states)
75 # convert to into canonical hash form
76 canonical_end_states = canonical_hash_form(end_states)
78 # for each start state do
79 Array(start_states).each do |start_state|
80 # validate start state
81 unless VALID_STATES.include?(start_state)
82 abort "Invalid state :#{start_state}. Must be one of the symbols #{VALID_STATES.map{|x| ":#{x}"}.join(', ')}"
85 # create a new metric to hold the watch, end states, and conditions
86 m = Metric.new(self, canonical_end_states)
88 # let the config file define some conditions on the metric
92 self.metrics[start_state] << m
96 ###########################################################################
100 ###########################################################################
103 self.transition(:up, :start) do |on|
109 self.transition(:up, :restart) do |on|
114 ###########################################################################
118 ###########################################################################
122 # start monitoring at the first available of the init or up states
123 if !self.metrics[:init].empty?
135 # Move from one state to another
137 msg = "#{self.name} move '#{self.state}' to '#{to_state}'"
141 # cleanup from current state
142 if from_state = self.state
143 self.metrics[from_state].each { |m| m.disable }
146 # perform action (if available)
147 self.action(to_state)
150 if [:start, :restart].include?(to_state) && self.metrics[to_state].empty?
156 self.metrics[to_state].each { |m| m.enable }
160 self.state = to_state
166 def action(a, c = nil)
169 Syslog.debug(self.start)
171 call_action(c, :start)
172 sleep(self.start_grace + self.grace)
175 Syslog.debug(self.restart)
177 call_action(c, :restart)
182 sleep(self.restart_grace + self.grace)
184 Syslog.debug(self.stop)
186 call_action(c, :stop)
187 sleep(self.stop_grace + self.grace)
191 def call_action(condition, action)
193 before_items = self.behaviors
194 before_items += [condition] if condition
195 before_items.each { |b| b.send("before_#{action}") }
197 @process.call_action(action)
200 after_items = self.behaviors
201 after_items += [condition] if condition
202 after_items.each { |b| b.send("after_#{action}") }
205 def canonical_hash_form(to)
206 to.instance_of?(Symbol) ? {true => to} : to
210 God.registry.add @process