add missing files

master
Justin Balthrop 2009-11-19 22:00:54 -08:00
parent 5667b6bfff
commit cc91cdcd14
3 changed files with 175 additions and 0 deletions

60
lib/bdb/base.rb Normal file
View File

@ -0,0 +1,60 @@
require 'bdb'
require 'tuple'
require 'bdb/environment'
require 'bdb/result_set'
class Bdb::Base
def initialize(opts)
@config = Bdb::Environment.config.merge(opts)
@indexes = {}
end
attr_reader :indexes
def config(config = {})
@config.merge!(config)
end
def index_by(field, opts = {})
raise "index on #{field} already exists" if indexes[field]
indexes[field] = opts
end
def environment
@environment ||= Bdb::Environment.new(config[:path], self)
end
def transaction(nested = true, &block)
environment.transaction(nested, &block)
end
def synchronize(&block)
environment.synchronize(&block)
end
def checkpoint(opts = {})
environment.synchronize(opts)
end
private
def get_field(field, value)
value.kind_of?(Hash) ? value[field] : value.send(field)
end
end
class Object
attr_accessor :bdb_locator_key
end
# Array comparison should try Tuple comparison first.
class Array
cmp = instance_method(:<=>)
define_method(:<=>) do |other|
begin
Tuple.dump(self) <=> Tuple.dump(other)
rescue TypeError => e
cmp.bind(self).call(other)
end
end
end

View File

@ -0,0 +1,74 @@
require 'bdb/base'
class Bdb::PartitionedDatabase < Bdb::Base
SEPARATOR = '__'
PARTITION_PATTERN = /^[-\w]*$/
def initialize(base_name, opts = {})
@base_name = base_name
@partition_by = opts.delete(:partition_by)
super(opts)
end
attr_reader :base_name, :partition_by, :partition
def databases
@databases ||= {}
end
def database(partition = nil)
partition ||= self.partition
raise 'partition value required' if partition.nil?
partition = partition.to_s
raise "invalid partition value: #{partition}" unless partition =~ PARTITION_PATTERN
databases[partition] ||= begin
name = [partition, base_name].join(SEPARATOR)
database = Bdb::Database.new(name, config)
indexes.each do |field, opts|
database.index_by(field, opts)
end
database
end
end
def partitions
Dir[environment.path + "/*#{SEPARATOR}#{base_name}"].collect do |file|
File.basename(file).split(SEPARATOR).first
end
end
def with_partition(partition)
@partition, old_partition = partition, @partition
yield
ensure
@partition = old_partition
end
def close
databases.each do |partition, database|
database.close
end
@databases.clear
end
def get(*keys, &block)
opts = keys.last.kind_of?(Hash) ? keys.last : {}
database(opts[partition_by]).get(*keys, &block)
end
def set(key, value, opts = {})
partition = get_field(partition_by, value)
database(partition).set(key, value, opts)
end
def delete(key, opts = {})
database(opts[partition_by]).delete(key)
end
# Deletes all records in the database. Beware!
def truncate!
partitions.each do |partition|
database(partition).truncate!
end
end
end

41
lib/bdb/result_set.rb Normal file
View File

@ -0,0 +1,41 @@
class Bdb::ResultSet
class LimitReached < Exception; end
def initialize(opts, &block)
@block = block
@count = 0
@limit = opts[:limit] || opts[:per_page]
@limit = @limit.to_i if @limit
@offset = opts[:offset] || (opts[:page] ? @limit * (opts[:page] - 1) : 0)
@offset = @offset.to_i if @offset
if @group = opts[:group]
raise 'block not supported with group' if @block
@results = hash_class.new
else
@results = []
end
end
attr_reader :count, :group, :limit, :offset, :results
def hash_class
@hash_class ||= defined?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash : Hash
end
def <<(item)
@count += 1
return if count <= offset
raise LimitReached if limit and count > limit + offset
if group
key = item.bdb_locator_key
group_key = group.is_a?(Fixnum) ? key[0,group] : key
(results[group_key] ||= []) << item
elsif @block
@block.call(item)
else
results << item
end
end
end