X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fregistry%2Ftc.rb;h=06013f8f796749aa2f2e751a1a179c6208218393;hb=440ef790a60a73e9b47050cddacddba59c61b30b;hp=8279f63a7fea25193f64b0ebe571618ba7112918;hpb=e1e90efaf2e9d9d09046e8877c276cb209c5e614;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/registry/tc.rb b/lib/rbot/registry/tc.rb index 8279f63a..06013f8f 100644 --- a/lib/rbot/registry/tc.rb +++ b/lib/rbot/registry/tc.rb @@ -5,6 +5,17 @@ begin require 'bdb' + if BDB::VERSION_MAJOR < 4 + fatal "Your bdb (Berkeley DB) version #{BDB::VERSION} is too old!" + fatal "rbot will only run with bdb version 4 or higher, please upgrade." + fatal "For maximum reliability, upgrade to version 4.2 or higher." + raise BDB::Fatal, BDB::VERSION + " is too old" + end + + if BDB::VERSION_MAJOR == 4 and BDB::VERSION_MINOR < 2 + warning "Your bdb (Berkeley DB) version #{BDB::VERSION} may not be reliable." + warning "If possible, try upgrade version 4.2 or later." + end rescue LoadError warning "rbot couldn't load the bdb module. Old registries won't be upgraded" rescue Exception => e @@ -12,22 +23,14 @@ rescue Exception => e end -if BDB::VERSION_MAJOR < 4 - fatal "Your bdb (Berkeley DB) version #{BDB::VERSION} is too old!" - fatal "rbot will only run with bdb version 4 or higher, please upgrade." - fatal "For maximum reliability, upgrade to version 4.2 or higher." - raise BDB::Fatal, BDB::VERSION + " is too old" -end -if BDB::VERSION_MAJOR == 4 and BDB::VERSION_MINOR < 2 - warning "Your bdb (Berkeley DB) version #{BDB::VERSION} may not be reliable." - warning "If possible, try upgrade version 4.2 or later." -end require 'tokyocabinet' module Irc + class DBFatal < Exception ; end + if defined? BDB # DBHash is for tying a hash to disk (using bdb). # Call it with an identifier, for example "mydata". It'll look for @@ -114,21 +117,25 @@ module Irc if absfilename && File.exist?(key) # db already exists, use it @db = DBTree.open_db(key) + @fname = key.dup elsif absfilename # create empty db @db = DBTree.create_db(key) + @fname = key.dup elsif File.exist? relfilename # db already exists, use it @db = DBTree.open_db relfilename + @fname = relfilename.dup else # create empty db @db = DBTree.create_db relfilename + @fname = relfilename.dup end oldbasename = (absfilename ? key : relfilename).gsub(/\.tdb$/, ".db") if File.exists? oldbasename and defined? BDB # upgrading warning "Upgrading old database #{oldbasename}..." - oldb = ::BDB::Btree.open(oldbasename, nil, "r", 0600) + oldb = ::BDB::CIBtree.open(oldbasename, nil, "r", 0600) oldb.each_key do |k| @db.outlist k @db.putlist k, (oldb.duplicates(k, false)) @@ -143,19 +150,51 @@ module Irc return @db.send(method, *args, &block) end + # Since TokyoCabinet does not have the concept of an environment, we have to do the + # database management ourselves. In particular, we have to keep a list of open + # registries to be sure we to close all of them on exit + @@bot_registries={ } + def self.close_bot_registries + @@bot_registries.each { |name, reg| reg.close } + @@bot_registries.clear + end + + def close + db = @@bot_registries.delete(@fname) + if db != @db + error "We think we have #{@db} from #{@fname}, TC pseudo-env gives us #{db}" + end + @db.close + end + def DBTree.create_db(name) debug "DBTree: creating empty db #{name}" + if @@bot_registries.key? name + error "DBTree: creating assumingly allocated db #{name}?!" + return @@bot_registries[name] + end db = TokyoCabinet::CIBDB.new res = db.open(name, TokyoCabinet::CIBDB::OREADER | TokyoCabinet::CIBDB::OCREAT | TokyoCabinet::CIBDB::OWRITER) - warning "DBTree: creating empty db #{name}: #{db.errmsg(db.ecode) unless res}" + if res + @@bot_registries[name] = db + else + error "DBTree: creating empty db #{name}: #{db.errmsg(db.ecode)}" + end return db end def DBTree.open_db(name) debug "DBTree: opening existing db #{name}" + if @@bot_registries.key? name + return @@bot_registries[name] + end db = TokyoCabinet::CIBDB.new res = db.open(name, TokyoCabinet::CIBDB::OREADER | TokyoCabinet::CIBDB::OWRITER) - warning "DBTree:opening db #{name}: #{db.errmsg(db.ecode) unless res}" + if res + @@bot_registries[name] = db + else + error "DBTree: opening db #{name}: #{db.errmsg(db.ecode)}" + end return db end @@ -168,7 +207,7 @@ module Irc end def DBTree.cleanup_env() - # no-op + DBTree.close_bot_registries end end @@ -191,29 +230,31 @@ class Bot # NB this function is called _early_ in init(), pretty much all you have to # work with is @bot.botclass. def upgrade_data + oldreg = @bot.path 'registry.db' if defined? DBHash - oldreg = @bot.path 'registry.db' newreg = @bot.path 'plugin_registry.db' if File.exist?(oldreg) log _("upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format") old = ::BDB::Hash.open(oldreg, nil, "r+", 0600) - new = TokyoCabinet::CIBDB.new - new.open(name, TokyoCabinet::CIBDB::OREADER | TokyoCabinet::CIBDB::OCREAT | TokyoCabinet::CIBDB::OWRITER) - old.each_key do |k| - new.outlist k - new.putlist k, (old.duplicates(k, false)) - end + new = ::BDB::CIBtree.open(newreg, nil, ::BDB::CREATE | ::BDB::EXCL, 0600) + old.each {|k,v| + new[k] = v + } old.close new.close File.rename(oldreg, oldreg + ".old") end else - warning "Won't upgrade data: BDB not installed" + warning "Won't upgrade data: BDB not installed" if File.exist? oldreg end end def upgrade_data2 oldreg = @bot.path 'plugin_registry.db' + if not defined? BDB + warning "Won't upgrade data: BDB not installed" if File.exist? oldreg + return + end newdir = @bot.path 'registry' if File.exist?(oldreg) Dir.mkdir(newdir) unless File.exist?(newdir) @@ -237,8 +278,8 @@ class Bot } end unless dbs.has_key?(prefix) - log _("creating db #{@bot.botclass}/registry/#{prefix}.db") - dbs[prefix] = TokyoCabinet::CIBDB.open("#{@bot.botclass}/registry/#{prefix}.db", + log _("creating db #{@bot.botclass}/registry/#{prefix}.tdb") + dbs[prefix] = TokyoCabinet::CIBDB.open("#{@bot.botclass}/registry/#{prefix}.tdb", TokyoCabinet::CIBDB::OREADER | TokyoCabinet::CIBDB::OCREAT | TokyoCabinet::CIBDB::OWRITER) end dbs[prefix][key] = v @@ -335,6 +376,7 @@ class Bot # debug "closing registry #{registry}" return if !@registry registry.close + @registry = nil end # convert value to string form for storing in the registry @@ -400,7 +442,7 @@ class Bot # just like Hash#each def each(set=nil, bulk=0, &block) return nil unless File.exist?(@filename) - registry.fwmkeys(set).each {|key| + registry.fwmkeys(set.to_s).each {|key| block.call(key, restore(registry[key])) } end @@ -408,7 +450,7 @@ class Bot # just like Hash#each_key def each_key(set=nil, bulk=0, &block) return nil unless File.exist?(@filename) - registry.fwmkeys(set).each do |key| + registry.fwmkeys(set.to_s).each do |key| block.call(key) end end @@ -416,7 +458,7 @@ class Bot # just like Hash#each_value def each_value(set=nil, bulk=0, &block) return nil unless File.exist?(@filename) - registry.fwmkeys(set).each do |key| + registry.fwmkeys(set.to_s).each do |key| block.call(restore(registry[key])) end end