add missing files
This commit is contained in:
parent
5667b6bfff
commit
cc91cdcd14
60
lib/bdb/base.rb
Normal file
60
lib/bdb/base.rb
Normal 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
|
74
lib/bdb/partitioned_database.rb
Normal file
74
lib/bdb/partitioned_database.rb
Normal 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
41
lib/bdb/result_set.rb
Normal 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
|
Loading…
Reference in a new issue