Project

General

Profile

Download (4.09 KB) Statistics
| Branch: | Tag: | Revision:
d32ee48a Marc Dequenes
#--
# CyborgHood, a distributed system management software.
364e4a96 Marc Dequènes (Duck)
# Copyright (c) 2009-2011 Marc Dequènes (Duck) <Duck@DuckCorp.org>
d32ee48a Marc Dequenes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++

ecdabe95 Marc Dequènes (Duck)
require 'cyborghood'
bc642412 Marc Dequènes (Duck)
require 'eventmachine'
a089227c Marc Dequènes (Duck)
require 'thread'
d7ae0ab2 Marc Dequènes (Duck)
require 'cyborghood/cyborg/dsl'
3b07cbbc duck

module CyborgHood
66cff75f Marc Dequènes (Duck)
module TaskAspect
def task(name, &block)
7988a0ad Marc Dequènes (Duck)
the_bot = self.is_a?(Cyborg) ? self : self.bot
DSL::Task.new(the_bot, name, &block)
66cff75f Marc Dequènes (Duck)
end

ce01c950 Marc Dequènes (Duck)
def schedule_task(callback = nil, &task)
66cff75f Marc Dequènes (Duck)
EventMachine.defer(task, callback)
end
end

3b07cbbc duck
class Cyborg
ecdabe95 Marc Dequènes (Duck)
include I18nTranslation
bindtextdomain("cyborghood", {:path => Config::L10N_DIR, :charset => "UTF-8"})
3b07cbbc duck
66cff75f Marc Dequènes (Duck)
include TaskAspect

90197e7b Marc Dequènes (Duck)
attr_reader :name, :services
45333094 Marc Dequènes (Duck)
90197e7b Marc Dequènes (Duck)
def initialize(services = nil)
@services = services
45333094 Marc Dequènes (Duck)
90197e7b Marc Dequènes (Duck)
@name = self.class.name.split("::").last
3b07cbbc duck
@config = Config.instance

# setup logs
unless @config.log.nil?
logger.output_level(@config.log.console_level) unless @config.log.console_level.nil?
ecdabe95 Marc Dequènes (Duck)
unless @config.log.path.nil?
if File.directory? @config.log.path
logger.log_to_file(File.join(@config.log.path, "ch_#{self.class.human_name}.log"))
3b07cbbc duck
else
ecdabe95 Marc Dequènes (Duck)
logger.fatal "Log path does not exist or is not a directory, exiting"
exit 1
3b07cbbc duck
end
end
end

06f77931 Marc Dequènes (Duck)
@channels = {}

050eca43 Marc Dequènes (Duck)
setup
3b07cbbc duck
ecdabe95 Marc Dequènes (Duck)
logger.info "Bot '#{self.human_name}' loaded"
3b07cbbc duck
end

06f77931 Marc Dequènes (Duck)
# #^.*/system$# categories are reserved
# but you may enhance or break the system as you wish
def get_channel(name)
return @channels[name] if @channels.has_key? name
@channels[name] = EventMachine::Channel.new
end
7d493229 Marc Dequènes (Duck)
06f77931 Marc Dequènes (Duck)
def drop_channel(name)
@channels.delete(name)
end

def setup
@system_notification_name = 'global/system'
@system_notification = get_channel(@system_notification_name)
7d493229 Marc Dequènes (Duck)
@system_notification_processing = @system_notification.subscribe do |msg|
process_system_notification(msg)
end
37b53292 Marc Dequènes (Duck)
EventMachine.error_handler do |e|
logger.error "Reactor error: " + e.to_s
logger.debug e.backtrace.join("\n")
end
050eca43 Marc Dequènes (Duck)
end

ecdabe95 Marc Dequènes (Duck)
def run
logger.info "Bot starting"
bc642412 Marc Dequènes (Duck)
EventMachine.run do
start_work
end
45333094 Marc Dequènes (Duck)
rescue EventMachine::ConnectionNotBound
37b53292 Marc Dequènes (Duck)
logger.error "Reactor error: Internal error (EventMachine::ConnectionNotBound)"
bc642412 Marc Dequènes (Duck)
end

def start_work
# use "aspects" Modules to define behaviors
050eca43 Marc Dequènes (Duck)
end

a089227c Marc Dequènes (Duck)
def stop(condition)
050eca43 Marc Dequènes (Duck)
logger.info "Bot was asked to stop..."
a089227c Marc Dequènes (Duck)
34bef607 Marc Dequènes (Duck)
yield if block_given?
a089227c Marc Dequènes (Duck)
case condition
when :when_finished
wait_until_ready_to_stop
when :quickly
# try to stop gracefully
DSL::Task.stop_all
wait_until_ready_to_stop
when :at_once
# it won't wait for anything to finish…
exit
end
f292535b Marc Dequènes (Duck)
end

a089227c Marc Dequènes (Duck)
# core capabilities
def capabilities
[]
end

protected

def stop_gracefully
45333094 Marc Dequènes (Duck)
end

a089227c Marc Dequènes (Duck)
def try_stop
45333094 Marc Dequènes (Duck)
logger.info "Bot stopping"
f292535b Marc Dequènes (Duck)
EventMachine.next_tick { EventMachine.stop_event_loop }
bc642412 Marc Dequènes (Duck)
end

a089227c Marc Dequènes (Duck)
def ready_to_stop?
DSL::Task.idle?
end

def wait_until_ready_to_stop
e321ca6f Marc Dequènes (Duck)
if ready_to_stop?
06f77931 Marc Dequènes (Duck)
@system_notification.unsubscribe(@system_notification_processing)
@system_notification_processing = nil
drop_channel(@system_notification_name)

a089227c Marc Dequènes (Duck)
try_stop
e321ca6f Marc Dequènes (Duck)
else
a089227c Marc Dequènes (Duck)
EventMachine.next_tick { wait_until_ready_to_stop }
e321ca6f Marc Dequènes (Duck)
end
end

7d493229 Marc Dequènes (Duck)
def process_system_notification(msg)
end
050eca43 Marc Dequènes (Duck)
end
cec96847 Marc Dequènes (Duck)
autoload :BotNet, 'cyborghood/cyborg/botnet'
3b07cbbc duck
end