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))
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
end
def DBTree.cleanup_env()
- # no-op
+ DBTree.close_bot_registries
end
end
# debug "closing registry #{registry}"
return if !@registry
registry.close
+ @registry = nil
end
# convert value to string form for storing in the registry
# 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
# 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
# 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