Sutto-marvin 0.4.0 → 0.8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/marvin +22 -156
- data/handlers/keiki_thwopper.rb +21 -0
- data/handlers/tweet_tweet.rb +1 -3
- data/lib/marvin/abstract_client.rb +75 -189
- data/lib/marvin/abstract_parser.rb +9 -11
- data/lib/marvin/base.rb +134 -101
- data/lib/marvin/client/actions.rb +104 -0
- data/lib/marvin/client/default_handlers.rb +97 -0
- data/lib/marvin/command_handler.rb +60 -49
- data/lib/marvin/console.rb +4 -31
- data/lib/marvin/core_commands.rb +30 -12
- data/lib/marvin/distributed/client.rb +225 -0
- data/lib/marvin/distributed/handler.rb +85 -0
- data/lib/marvin/distributed/protocol.rb +88 -0
- data/lib/marvin/distributed/server.rb +154 -0
- data/lib/marvin/distributed.rb +4 -10
- data/lib/marvin/dsl.rb +103 -0
- data/lib/marvin/exception_tracker.rb +7 -4
- data/lib/marvin/irc/client.rb +127 -99
- data/lib/marvin/irc/event.rb +14 -10
- data/lib/marvin/irc.rb +0 -1
- data/lib/marvin/middle_man.rb +1 -1
- data/lib/marvin/parsers/command.rb +10 -8
- data/lib/marvin/parsers/prefixes/host_mask.rb +12 -7
- data/lib/marvin/parsers/prefixes/server.rb +1 -1
- data/lib/marvin/parsers/ragel_parser.rb +59 -52
- data/lib/marvin/parsers/ragel_parser.rl +6 -7
- data/lib/marvin/parsers/simple_parser.rb +4 -9
- data/lib/marvin/parsers.rb +1 -2
- data/lib/marvin/settings.rb +29 -79
- data/lib/marvin/test_client.rb +20 -26
- data/lib/marvin/util.rb +10 -3
- data/lib/marvin.rb +42 -39
- data/templates/boot.erb +3 -0
- data/templates/connections.yml.erb +10 -0
- data/templates/debug_handler.erb +5 -0
- data/templates/hello_world.erb +10 -0
- data/templates/rakefile.erb +15 -0
- data/templates/settings.yml.erb +8 -0
- data/{config/setup.rb → templates/setup.erb} +8 -10
- data/templates/test_helper.erb +17 -0
- data/test/abstract_client_test.rb +63 -0
- data/test/parser_comparison.rb +2 -2
- data/test/parser_test.rb +3 -3
- data/test/test_helper.rb +58 -6
- metadata +51 -83
- data/README.textile +0 -105
- data/TUTORIAL.textile +0 -54
- data/VERSION.yml +0 -4
- data/config/boot.rb +0 -14
- data/config/connections.yml.sample +0 -5
- data/config/settings.yml.sample +0 -13
- data/handlers/logging_handler.rb +0 -89
- data/lib/marvin/core_ext.rb +0 -11
- data/lib/marvin/daemon.rb +0 -71
- data/lib/marvin/data_store.rb +0 -73
- data/lib/marvin/dispatchable.rb +0 -99
- data/lib/marvin/distributed/dispatch_handler.rb +0 -83
- data/lib/marvin/distributed/drb_client.rb +0 -78
- data/lib/marvin/distributed/ring_server.rb +0 -41
- data/lib/marvin/handler.rb +0 -12
- data/lib/marvin/irc/server/abstract_connection.rb +0 -84
- data/lib/marvin/irc/server/base_connection.rb +0 -66
- data/lib/marvin/irc/server/channel.rb +0 -115
- data/lib/marvin/irc/server/named_store.rb +0 -14
- data/lib/marvin/irc/server/remote_interface.rb +0 -77
- data/lib/marvin/irc/server/user/handle_mixin.rb +0 -140
- data/lib/marvin/irc/server/user.rb +0 -5
- data/lib/marvin/irc/server/user_connection.rb +0 -134
- data/lib/marvin/irc/server/virtual_user_connection.rb +0 -80
- data/lib/marvin/irc/server.rb +0 -71
- data/lib/marvin/loader.rb +0 -149
- data/lib/marvin/logger.rb +0 -86
- data/lib/marvin/options.rb +0 -42
- data/lib/marvin/parsers/regexp_parser.rb +0 -93
- data/lib/marvin/status.rb +0 -72
- data/script/client +0 -3
- data/script/console +0 -3
- data/script/distributed_client +0 -3
- data/script/install +0 -1
- data/script/ring_server +0 -4
- data/script/server +0 -4
- data/script/status +0 -3
- data/spec/marvin/abstract_client_test.rb +0 -38
- data/spec/spec_helper.rb +0 -14
data/handlers/logging_handler.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
# A Simple Channel Logger, built for the
|
2
|
-
# #offrails community. Please note that this
|
3
|
-
# relies on models etc. inside the Rails App.
|
4
|
-
# it's suited for modification of subclassing
|
5
|
-
# if you wish to write your own Channel Logger.
|
6
|
-
# I plan on open sourcing the app sometime in
|
7
|
-
# the near future.
|
8
|
-
class LoggingHandler < Marvin::CommandHandler
|
9
|
-
|
10
|
-
class_inheritable_accessor :connection, :setup
|
11
|
-
attr_accessor :listening, :users
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
super
|
15
|
-
logger.debug "Setting up LoggingHandler"
|
16
|
-
self.setup!
|
17
|
-
self.users = {}
|
18
|
-
end
|
19
|
-
|
20
|
-
# Control
|
21
|
-
|
22
|
-
exposes :listen, :earmuffs
|
23
|
-
|
24
|
-
desc "Makes me listen up and take not of what you're saying."
|
25
|
-
def listen(data)
|
26
|
-
unless listening?
|
27
|
-
@listening = true
|
28
|
-
reply "Busted! I heard _everything_ you said ;)"
|
29
|
-
else
|
30
|
-
reply "Uh, You never asked me to put my earmuffs on?"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
desc "Sends me off into a corner with my ear muffs so you can have your discussions in peace"
|
35
|
-
def earmuffs(data)
|
36
|
-
if listening?
|
37
|
-
@listening = false
|
38
|
-
reply "Oh hai, I'm not listening anymore."
|
39
|
-
else
|
40
|
-
reply "I've already put the earmuffs on!"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def listening?
|
45
|
-
@listening
|
46
|
-
end
|
47
|
-
|
48
|
-
# The actual logging
|
49
|
-
|
50
|
-
on_event :incoming_message do
|
51
|
-
log_message(options.nick, options.target, options.message)
|
52
|
-
end
|
53
|
-
|
54
|
-
on_event :outgoing_message do
|
55
|
-
log_message(client.nickname, options.target, options.message)
|
56
|
-
end
|
57
|
-
|
58
|
-
on_event :incoming_action do
|
59
|
-
log_message(options.nick, options.target, "ACTION \01#{options.message}\01")
|
60
|
-
end
|
61
|
-
|
62
|
-
def log_message(from, to, message)
|
63
|
-
return unless listening?
|
64
|
-
ensure_connection_is_alive # Before Logging, ensure that the connection is alive.
|
65
|
-
self.users[from.strip] ||= IrcHandle.find_or_create_by_name(from.strip)
|
66
|
-
self.users[from.strip].messages.create :message => message, :target => to
|
67
|
-
end
|
68
|
-
|
69
|
-
# Our General Tasks
|
70
|
-
|
71
|
-
def setup!
|
72
|
-
return true if self.setup
|
73
|
-
load_prerequisites
|
74
|
-
self.setup = true
|
75
|
-
self.listening = true
|
76
|
-
end
|
77
|
-
|
78
|
-
def load_prerequisites
|
79
|
-
require File.join(Marvin::Settings.rails_root, "config/environment")
|
80
|
-
end
|
81
|
-
|
82
|
-
def ensure_connection_is_alive
|
83
|
-
unless ActiveRecord::Base.connection.active?
|
84
|
-
ActiveRecord::Base.connection.reconnect!
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
end
|
data/lib/marvin/core_ext.rb
DELETED
data/lib/marvin/daemon.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
module Marvin
|
2
|
-
class Daemon
|
3
|
-
class << self
|
4
|
-
|
5
|
-
def alive?(pid)
|
6
|
-
return Process.getpgid(pid) != -1
|
7
|
-
rescue Errno::ESRCH
|
8
|
-
return false
|
9
|
-
end
|
10
|
-
|
11
|
-
def kill_all(type = :all)
|
12
|
-
if type == :all
|
13
|
-
files = Dir[Marvin::Settings.root / "tmp/pids/*.pid"]
|
14
|
-
files.each { |f| kill_all_from f }
|
15
|
-
elsif type.is_a?(Symbol)
|
16
|
-
kill_all_from(pid_file_for(type))
|
17
|
-
end
|
18
|
-
return nil
|
19
|
-
end
|
20
|
-
|
21
|
-
def daemonize!
|
22
|
-
exit if fork
|
23
|
-
Process.setsid
|
24
|
-
exit if fork
|
25
|
-
self.write_pid
|
26
|
-
File.umask 0000
|
27
|
-
STDIN.reopen "/dev/null"
|
28
|
-
STDOUT.reopen "/dev/null", "a"
|
29
|
-
STDERR.reopen STDOUT
|
30
|
-
Marvin::Settings.verbose = false
|
31
|
-
end
|
32
|
-
|
33
|
-
def cleanup!
|
34
|
-
f = pids_file_for(Marvin::Loader.type)
|
35
|
-
FileUtils.rm_f(f) if (pids_from(f) - Process.pid).blank?
|
36
|
-
end
|
37
|
-
|
38
|
-
def pids_for_type(type)
|
39
|
-
pids_from(pid_file_for(type))
|
40
|
-
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
def kill_all_from(file)
|
45
|
-
pids = pids_from(file)
|
46
|
-
pids.each { |p| Process.kill("TERM", p) unless p == Process.pid }
|
47
|
-
FileUtils.rm_f(file)
|
48
|
-
rescue => e
|
49
|
-
STDOUT.puts e.inspect
|
50
|
-
end
|
51
|
-
|
52
|
-
def pid_file_for(type)
|
53
|
-
Marvin::Settings.root / "tmp" / "pids" / "marvin-#{type.to_s.underscore}.pid"
|
54
|
-
end
|
55
|
-
|
56
|
-
def pids_from(file)
|
57
|
-
return [] unless File.exist?(file)
|
58
|
-
pids = File.read(file)
|
59
|
-
pids = pids.split("\n").map { |l| l.strip.to_i(10) }.select { |p| alive?(p) }
|
60
|
-
end
|
61
|
-
|
62
|
-
def write_pid
|
63
|
-
f = pid_file_for(Marvin::Loader.type)
|
64
|
-
pids = pids_from(f)
|
65
|
-
pids << Process.pid unless pids.include?(Process.pid)
|
66
|
-
File.open(f, "w+") { |f| f.puts pids.join("\n") }
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/marvin/data_store.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Marvin
|
4
|
-
# Implements a simple datastore interface, designed to make
|
5
|
-
# it easy to develop handlers which have persistent data.
|
6
|
-
class DataStore
|
7
|
-
|
8
|
-
cattr_accessor :logger, :registered_stores
|
9
|
-
self.logger = Marvin::Logger.logger
|
10
|
-
self.registered_stores = {}
|
11
|
-
|
12
|
-
# Returns the path to the data store relative to this file.
|
13
|
-
# Used when loading / dumping the data.
|
14
|
-
def self.datastore_location
|
15
|
-
path = Marvin::Settings[:datastore_location] ? Marvin::Settings.datastore_location : "tmp/datastore.json"
|
16
|
-
return Marvin::Settings.root / path
|
17
|
-
end
|
18
|
-
|
19
|
-
# Dump the current data store contents to file.
|
20
|
-
def self.dump!
|
21
|
-
File.open(self.datastore_location, "w+") do |f|
|
22
|
-
f.write self.registered_stores.to_json
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Load the current data store contents from file.
|
27
|
-
def self.load!
|
28
|
-
results = {}
|
29
|
-
if File.exists?(self.datastore_location)
|
30
|
-
begin
|
31
|
-
json = JSON.load(File.read(self.datastore_location))
|
32
|
-
results = json if json.is_a?(Hash)
|
33
|
-
rescue JSON::ParserError
|
34
|
-
end
|
35
|
-
end
|
36
|
-
self.registered_stores = results
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
# For each individual datastore.
|
41
|
-
|
42
|
-
attr_accessor :name
|
43
|
-
|
44
|
-
def initialize(name)
|
45
|
-
self.name = name.to_s
|
46
|
-
self.registered_stores ||= {}
|
47
|
-
self.registered_stores[self.name] ||= {}
|
48
|
-
end
|
49
|
-
|
50
|
-
def [](key)
|
51
|
-
((self.registered_stores||={})[self.name]||={})[key.to_s]
|
52
|
-
end
|
53
|
-
|
54
|
-
def []=(key,value)
|
55
|
-
self.registered_stores[self.name][key.to_s] = value
|
56
|
-
end
|
57
|
-
|
58
|
-
def method_missing(name, *args, &blk)
|
59
|
-
if name.to_s =~ /^(.*)=$/i
|
60
|
-
self[$1.to_s] = args.first
|
61
|
-
elsif self.registered_stores[self.name].has_key?(name.to_s)
|
62
|
-
return self.registered_stores[self.name][name.to_s]
|
63
|
-
else
|
64
|
-
super(name, *args, &blk)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_hash
|
69
|
-
self.registered_stores[self.name]
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
data/lib/marvin/dispatchable.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
module Marvin
|
2
|
-
# = Marvin::Dispatchable
|
3
|
-
# A Generic mixin which lets you define an object
|
4
|
-
# Which accepts handlers which can have arbitrary
|
5
|
-
# events dispatched.
|
6
|
-
# == Usage
|
7
|
-
#
|
8
|
-
# class X
|
9
|
-
# include Marvin::Dispatchable
|
10
|
-
# self.handlers << SomeHandler.new
|
11
|
-
# end
|
12
|
-
# X.new.dispatch(:name, {:args => "Values"})
|
13
|
-
#
|
14
|
-
# Will first check if SomeHandler#handle_name exists,
|
15
|
-
# calling handle_name({:args => "Values"}) if it does,
|
16
|
-
# otherwise calling SomeHandler#handle(:name, {:args => "Values"})
|
17
|
-
module Dispatchable
|
18
|
-
|
19
|
-
def self.included(parent)
|
20
|
-
parent.class_eval do
|
21
|
-
include InstanceMethods
|
22
|
-
extend ClassMethods
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
module InstanceMethods
|
27
|
-
|
28
|
-
# Returns the handlers registered on this class,
|
29
|
-
# used inside +dispatch+. Note that it will call
|
30
|
-
# dup on each of the objects to get a new instance.
|
31
|
-
# please ensure your object acts accordingly.
|
32
|
-
def handlers
|
33
|
-
@handlers ||= self.class.handlers.map { |h| h.dup }
|
34
|
-
end
|
35
|
-
|
36
|
-
# Dispatch an 'event' with a given name to the handlers
|
37
|
-
# registered on the current class. Used as a nicer way of defining
|
38
|
-
# behaviours that should occur under a given set of circumstances.
|
39
|
-
# == Params
|
40
|
-
# +name+: The name of the current event
|
41
|
-
# +opts+: an optional hash of options to pass
|
42
|
-
def dispatch(name, opts = {})
|
43
|
-
# The full handler name is the method we call given it exists.
|
44
|
-
full_handler_name = :"handle_#{name.to_s.underscore}"
|
45
|
-
# First, dispatch locally if the method is defined.
|
46
|
-
if self.respond_to?(full_handler_name)
|
47
|
-
self.send(full_handler_name, opts)
|
48
|
-
end
|
49
|
-
# Iterate through all of the registered handlers,
|
50
|
-
# If there is a method named handle_<event_name>
|
51
|
-
# defined we sent that otherwise we call the handle
|
52
|
-
# method on the handler. Note that the handle method
|
53
|
-
# is the only required aspect of a handler. An improved
|
54
|
-
# version of this would likely cache the respond_to?
|
55
|
-
# call.
|
56
|
-
self.handlers.each do |handler|
|
57
|
-
if handler.respond_to?(full_handler_name)
|
58
|
-
handler.send(full_handler_name, opts)
|
59
|
-
else
|
60
|
-
handler.handle name, opts
|
61
|
-
end
|
62
|
-
end
|
63
|
-
# If we get the HaltHandlerProcessing exception, we
|
64
|
-
# catch it and continue on our way. In essence, we
|
65
|
-
# stop the dispatch of events to the next set of the
|
66
|
-
# handlers.
|
67
|
-
rescue HaltHandlerProcessing => e
|
68
|
-
Marvin::Logger.info "Halting processing chain"
|
69
|
-
rescue Exception => e
|
70
|
-
Marvin::ExceptionTracker.log(e)
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
module ClassMethods
|
76
|
-
|
77
|
-
# Return an array of all registered handlers, stored in the
|
78
|
-
# class variable @@handlers. Used inside the #handlers instance
|
79
|
-
# method as well as inside things such as register_handler.
|
80
|
-
def handlers
|
81
|
-
@@handlers ||= []
|
82
|
-
end
|
83
|
-
|
84
|
-
# Assigns a new array of handlers and assigns each.
|
85
|
-
def handlers=(new_value)
|
86
|
-
@@handlers = []
|
87
|
-
new_value.to_a.each { |h| register_handler h }
|
88
|
-
end
|
89
|
-
|
90
|
-
# Appends a handler to the list of handlers for this object.
|
91
|
-
# Handlers are called in the order they are registered.
|
92
|
-
def register_handler(handler)
|
93
|
-
self.handlers << handler unless handler.nil? || !handler.respond_to?(:handle)
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'rinda/ring'
|
2
|
-
require 'rinda/tuplespace'
|
3
|
-
|
4
|
-
DRb.start_service
|
5
|
-
|
6
|
-
module Marvin
|
7
|
-
module Distributed
|
8
|
-
|
9
|
-
# Handler to provide
|
10
|
-
class DispatchHandler < Marvin::Base
|
11
|
-
|
12
|
-
LOOKUP_TIMEOUT = 0.5
|
13
|
-
|
14
|
-
# Tell the client that we shouldn't be dumped.
|
15
|
-
Marvin::AbstractClient.class_eval { include(DRbUndumped) }
|
16
|
-
|
17
|
-
# Get the ring server - if it exists, we will return the current
|
18
|
-
# instance other wise it follows a few steps to try and find a new
|
19
|
-
# one. Since there can be a delay in getting a response, we'll only
|
20
|
-
# check every 5 messages.
|
21
|
-
def ring_server
|
22
|
-
if @@rs.nil? && (@lookup_attempts ||= 6) > 5
|
23
|
-
@lookup_attempts = 0
|
24
|
-
@@rs = Rinda::RingFinger.finger.lookup_ring(LOOKUP_TIMEOUT)
|
25
|
-
logger.info "Found new ring server => #{@@rs.__drburi}"
|
26
|
-
elsif @@rs.nil?
|
27
|
-
@lookup_attempts += 1
|
28
|
-
end
|
29
|
-
return @@rs
|
30
|
-
rescue RingNotFound
|
31
|
-
@@rs = nil
|
32
|
-
end
|
33
|
-
|
34
|
-
# Takes an incoming messsage and does all the fancy
|
35
|
-
# Stuff with it.
|
36
|
-
def handle(message, options)
|
37
|
-
# Don't forward lines for the moment to halve the traffic.
|
38
|
-
return if message == :incoming_line
|
39
|
-
super(message, options)
|
40
|
-
dispatch(message, options)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Attempts to add a message to the current tuple space,
|
44
|
-
# adding it to a message queue if it can't be added.
|
45
|
-
# If there are many items, it will log a warning.
|
46
|
-
# TODO: Improve it to dump messages to disk at a predefined limit.
|
47
|
-
def dispatch(name, options)
|
48
|
-
options[:dispatched_at] ||= Time.now
|
49
|
-
tuple = [:marvin_event, Marvin::Settings.distributed_namespace, name, options, self.client]
|
50
|
-
begin
|
51
|
-
(@queued_messages ||= []) << tuple
|
52
|
-
if self.ring_server.nil?
|
53
|
-
size = @queued_messages.size
|
54
|
-
if size > 0 && size % 25 == 0
|
55
|
-
logger.warn "Dispatch handler queue is currently holding #{size} items"
|
56
|
-
end
|
57
|
-
else
|
58
|
-
logger.debug "Writing #{@queued_messages.size} message to the ring server"
|
59
|
-
@queued_messages.dup.each do |t|
|
60
|
-
ring_server.write(t)
|
61
|
-
@queued_messages.delete(t)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
rescue
|
65
|
-
# Reset the ring finger to the next choice.
|
66
|
-
logger.debug "Ring server unavailable, resetting..."
|
67
|
-
@@rs = nil
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Register this as a handler, but only if we're
|
72
|
-
# running in "client mode" - in other words, we
|
73
|
-
# want to make sure it won't start up an infinite
|
74
|
-
# loop.
|
75
|
-
def self.register!(*args)
|
76
|
-
# DO NOT register if this is not a normal client.
|
77
|
-
return unless Marvin::Loader.type == :client
|
78
|
-
super
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module Marvin
|
2
|
-
module Distributed
|
3
|
-
# A method for operating on marvin objects.
|
4
|
-
class DRbClient
|
5
|
-
|
6
|
-
# Wait 1 second on a lookup.
|
7
|
-
LOOKUP_TIMEOUT = 1
|
8
|
-
|
9
|
-
class << self
|
10
|
-
|
11
|
-
@@handlers = []
|
12
|
-
attr_accessor :stopped
|
13
|
-
|
14
|
-
def register_handler(handler)
|
15
|
-
@@handlers << handler unless handler.nil? || !handler.respond_to?(:handle)
|
16
|
-
end
|
17
|
-
|
18
|
-
def dispatch(name, opts, client)
|
19
|
-
Marvin::Logger.debug "Processing Event: #{name}"
|
20
|
-
full_handler_name = :"handle_#{name.to_s.underscore}"
|
21
|
-
@@handlers.each do |handler|
|
22
|
-
has_client = handler.respond_to?(:client=)
|
23
|
-
handler.client = client if has_client
|
24
|
-
if handler.respond_to?(full_handler_name)
|
25
|
-
handler.send(full_handler_name, opts)
|
26
|
-
else
|
27
|
-
handler.handle name, opts
|
28
|
-
end
|
29
|
-
handler.client = nil if has_client
|
30
|
-
end
|
31
|
-
rescue HaltHandlerProcessing => e
|
32
|
-
Marvin::Logger.info "Halting processing chain"
|
33
|
-
rescue Exception => e
|
34
|
-
Marvin::ExceptionTracker.log(e)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Starts up a drb processor / client, and walks through the process of dealing
|
38
|
-
# with it / processing events.
|
39
|
-
def run
|
40
|
-
self.stopped = false
|
41
|
-
Marvin::Logger.info "Starting up DRb Client"
|
42
|
-
DRb.start_service
|
43
|
-
# Loop through, making sure we have a valid
|
44
|
-
# RingFinger and then process events as they
|
45
|
-
# appear.
|
46
|
-
enter_loop!
|
47
|
-
end
|
48
|
-
|
49
|
-
def stop
|
50
|
-
self.stopped = true
|
51
|
-
end
|
52
|
-
|
53
|
-
def ring_server
|
54
|
-
@ring_server = Rinda::RingFinger.finger.lookup_ring(LOOKUP_TIMEOUT) if @ring_server.nil?
|
55
|
-
return @ring_server
|
56
|
-
rescue RingNotFound
|
57
|
-
@ring_server = nil
|
58
|
-
end
|
59
|
-
|
60
|
-
def enter_loop!
|
61
|
-
Marvin::Logger.info "Entering processing loop"
|
62
|
-
while !self.stopped
|
63
|
-
begin
|
64
|
-
unless self.ring_server.blank?
|
65
|
-
event = self.ring_server.take([:marvin_event, Marvin::Settings.distributed_namespace, nil, nil, nil], 2)
|
66
|
-
dispatch(*event[2..-1]) unless event.blank?
|
67
|
-
end
|
68
|
-
rescue
|
69
|
-
# Reset the ring server on event of connection refused etc.
|
70
|
-
@ring_server = nil
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'rinda/ring'
|
2
|
-
require 'rinda/tuplespace'
|
3
|
-
|
4
|
-
module Marvin
|
5
|
-
module Distributed
|
6
|
-
class RingServer
|
7
|
-
|
8
|
-
attr_accessor :tuple_space, :ring_server
|
9
|
-
cattr_accessor :logger
|
10
|
-
self.logger = Marvin::Logger
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
self.tuple_space = Rinda::TupleSpace.new
|
14
|
-
if Marvin::Settings.log_level == :debug
|
15
|
-
observer = self.tuple_space.notify('write', [:marvin_event, Marvin::Settings.distributed_namespace, nil, nil, nil])
|
16
|
-
Thread.start do
|
17
|
-
observer.each do |i|
|
18
|
-
event_name, args = i[1][2..3]
|
19
|
-
Marvin::Logger.logger.debug "Marvin event added - #{event_name.inspect} w/ #{args.inspect}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
self.ring_server = Rinda::RingServer.new(self.tuple_space)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.run
|
27
|
-
begin
|
28
|
-
logger.info "Starting up DRb"
|
29
|
-
drb_server = DRb.start_service
|
30
|
-
logger.info "Creating TupleSpace & Ring Server Instances - Running on #{DRb.uri}"
|
31
|
-
self.new
|
32
|
-
logger.info "Started - Joining thread."
|
33
|
-
DRb.thread.join
|
34
|
-
rescue
|
35
|
-
logger.fatal "Error starting ring server - please ensure another instance isn't already running."
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/marvin/handler.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
module Marvin
|
2
|
-
module Handler
|
3
|
-
|
4
|
-
# Received a given +message+ with a set of default
|
5
|
-
# +opts+ (defaulting back to an empty hash), which
|
6
|
-
# will be used to perform some sort of action.
|
7
|
-
def handle(message, opts = {})
|
8
|
-
Marvin::Logger.debug "NOP handle - got message #{message.inspect}"
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
module Marvin::IRC::Server
|
2
|
-
class AbstractConnection
|
3
|
-
include Marvin::Dispatchable
|
4
|
-
|
5
|
-
cattr_accessor :connections, :logger, :alive
|
6
|
-
self.connections = []
|
7
|
-
self.logger = Marvin::Logger
|
8
|
-
|
9
|
-
attr_accessor :connection
|
10
|
-
|
11
|
-
# Create a new connection with a given parent
|
12
|
-
# and an incoming buffer of messages
|
13
|
-
def initialize(parent, buffer = [])
|
14
|
-
@connection = parent
|
15
|
-
buffer.each { |line| receive_line(line) }
|
16
|
-
end
|
17
|
-
|
18
|
-
def receive_line(line)
|
19
|
-
dispatch :incoming_line, :line => line
|
20
|
-
event = Marvin::Settings.default_parser.parse(line)
|
21
|
-
dispatch(event.to_incoming_event_name, event.to_hash) unless event.nil?
|
22
|
-
end
|
23
|
-
|
24
|
-
def send_line(line)
|
25
|
-
@connection.send_line(line)
|
26
|
-
end
|
27
|
-
|
28
|
-
def process_connect
|
29
|
-
@alive = true
|
30
|
-
# Send the welcome notice / auth command.
|
31
|
-
command :NOTICE, "AUTH", ":Marvin v#{Marvin.version} initialized, welcome."
|
32
|
-
dispatch :client_connected, :client => self
|
33
|
-
end
|
34
|
-
|
35
|
-
def process_disconnect
|
36
|
-
@@connections.delete(self)
|
37
|
-
@alive = false
|
38
|
-
dispatch :client_disconnected, :client => self
|
39
|
-
end
|
40
|
-
|
41
|
-
class << self
|
42
|
-
|
43
|
-
# Return an array of all registered handlers, stored in the
|
44
|
-
# class variable @@handlers. Used inside the #handlers instance
|
45
|
-
# method as well as inside things such as register_handler.
|
46
|
-
def handlers
|
47
|
-
(@@handlers ||= {})[self] ||= []
|
48
|
-
end
|
49
|
-
|
50
|
-
# Assigns a new array of handlers and assigns each.
|
51
|
-
def handlers=(new_value)
|
52
|
-
(@@handlers ||= {})[self] = []
|
53
|
-
new_value.to_a.each { |h| register_handler h }
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
def dispatch(name, opts = {})
|
59
|
-
opts[:connection] ||= self
|
60
|
-
super
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def command(name, *args)
|
66
|
-
opts = args.extract_options!
|
67
|
-
formatted = [name.to_s.upcase, *args].join(" ")
|
68
|
-
formatted = ":#{opts[:prefix]} #{formatted}" if opts[:prefix]
|
69
|
-
send_line formatted
|
70
|
-
end
|
71
|
-
|
72
|
-
def peer_name
|
73
|
-
return @peer_name unless @peer_name.blank?
|
74
|
-
sock_addr = @connection.get_peername
|
75
|
-
begin
|
76
|
-
@peer_name = Socket.getnameinfo(sock_addr, Socket::NI_NAMEREQD).first
|
77
|
-
rescue
|
78
|
-
@peer_name = Socket.getnameinfo(sock_addr).first
|
79
|
-
end
|
80
|
-
return @peer_name
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|