syslog2logan/bin/s2l.rb

153 lines
2.8 KiB
Ruby
Executable File

#!/usr/bin/ruby
require 'rubygems'
require 'sbdb'
require 'uuidtools'
require 'socket'
require 'select'
class S2L < Select::Server
def init p
super p
@dbs = p[:dbs]
end
def event_new_client a
{ :clientclass => S2L::Socket, :dbs => @dbs }
end
end
module Kernel
def debug( *p) logger :debug, *p end
def info( *p) logger :info, *p end
def warn( *p) logger :warn, *p end
def error( *p) logger :error, *p end
def fatal( *p) logger :fatal, *p end
def logger l, *p
p = p.first if p.length == 1
$stderr.puts [Time.now, l, p].inspect
end
private :logger
end
class S2L::Socket < Select::Socket
def init opts
@dbs = opts[ :dbs]
super opts
end
def event_line v
@dbs.emit v
end
alias emit event_line
end
class Rotate
def initialize db, &e
@rdb, @env, @dbs = db, db.home, {}
self.hash = e || lambda {|k|
[UUIDTools::UUID.parse_raw( k).timestamp.to_i/60/60/24].pack 'N'
}
end
def hash= e
self.hash &e
end
def hash &e
@hash_func = e if e
@hash_func
end
def hashing k
@hash_func.call k
end
def db k
n = @rdb[ h]
if n
n = UUIDTools::UUID.parse_raw n
else
n = UUIDTools::UUID.timestamp_create
@rdb[ h] = n.raw
end
info :open => n.to_s
@env[ n.to_s, 'logs', SBDB::Btree, SBDB::CREATE | SBDB::AUTO_COMMIT]
@env[ "#{n}.newids", 'logs', SBDB::Queue, SBDB::CREATE | SBDB::AUTO_COMMIT]
end
def sync
@dbs.each{|n,db|db.sync}
@rdb.sync
end
def close
@dbs.each{|n,db|db.close 0}
@rdb.close 0
end
def put v
id = UUIDTools::UUID.timestamp_create
s = [0x10, v].pack 'Na*'
db(id.raw)[ id.raw] = s
end
alias emit put
end
class Retries
attr_accessor :max, :range
attr_reader :count, :last
def initialize max = 10, range = 10
@max, @range, @count, @last = max, range, 0, Time.now
end
def retry?
@count = @last + @range > Time.now ? @count + 1 : 1
@last = Time.now
@count < @max
end
def run ex, &e
begin e.call *args
rescue ex
retries.retry? and retry
end
end
end
$conf = {
:home => 'logs',
:server => [ '', 1514],
:retries => [10, 10]
}
info :create => {:home => $conf[:home]}
Dir.mkdir $conf[:home] rescue Errno::EEXIST
info :open => SBDB::Env
SBDB::Env.new( $conf[:home], SBDB::CREATE | SBDB::Env::INIT_TRANSACTION | Bdb::DB_AUTO_COMMIT) do |dbenv|
info :open => Rotate
dbs = Rotate.new dbenv[ 'rotates.db', 'rotates', SBDB::Btree, SBDB::CREATE | Bdb::DB_AUTO_COMMIT]
info :open => S2L
serv = S2L.new :sock => TCPServer.new( *$conf[:server]), :dbs => dbs
retries = Retries.new *$conf[:retries]
begin
info :run => serv
serv.run
info :shutdown => :stoped
rescue Interrupt
info :shutdown => :interrupted
rescue SignalException
info :shutdown => :signal
rescue Object
error :exception=>$!, :backtrace=>$!.backtrace
retries.retry? and retry
fatal "Too many retries (#{retries.count})"
info :shutdown => :fatal
end
info :close => dbenv
end
info :halted