2010-02-02 00:52:25 +01:00
|
|
|
require 'bdb'
|
|
|
|
require 'sbdb/cursor'
|
|
|
|
|
|
|
|
module SBDB
|
2010-02-06 11:50:52 +01:00
|
|
|
TYPES = []
|
2010-02-02 00:52:25 +01:00
|
|
|
class DB
|
|
|
|
UNKNOWN = Bdb::Db::UNKNOWN
|
|
|
|
BTREE = Bdb::Db::BTREE
|
|
|
|
HASH = Bdb::Db::HASH
|
|
|
|
QUEUE = Bdb::Db::QUEUE
|
|
|
|
ARRAY = RECNO = Bdb::Db::RECNO
|
2010-02-02 18:12:11 +01:00
|
|
|
RDONLY = READLONY = Bdb::DB_RDONLY
|
2010-02-05 19:08:30 +01:00
|
|
|
CONSUME = Bdb::DB_CONSUME
|
|
|
|
CONSUME_WAIT = Bdb::DB_CONSUME_WAIT
|
2010-02-02 00:52:25 +01:00
|
|
|
|
|
|
|
attr_reader :home
|
2010-03-09 19:09:22 +01:00
|
|
|
attr_accessor :txn
|
2010-02-02 00:52:25 +01:00
|
|
|
include Enumerable
|
|
|
|
def bdb_object() @db end
|
|
|
|
def sync() @db.sync end
|
2010-03-12 21:14:38 +01:00
|
|
|
def close( flg = nil) @db.close flg || 0 end
|
|
|
|
def cursor( &exe) Cursor.new self, &exe end
|
2010-02-02 00:52:25 +01:00
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def at key, txn = nil
|
|
|
|
@db.get _txn(txn), key.nil? ? nil : key.to_s, nil, 0
|
2010-02-23 19:39:27 +01:00
|
|
|
rescue Bdb::KeyEmpty
|
|
|
|
return nil
|
2010-02-06 00:41:43 +01:00
|
|
|
end
|
2010-03-11 00:18:38 +01:00
|
|
|
alias [] at
|
2010-02-06 00:41:43 +01:00
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def put key, val, txn = nil
|
|
|
|
if val.nil?
|
|
|
|
@db.del _txn(txn), key.to_s, 0
|
2010-02-05 19:08:30 +01:00
|
|
|
else
|
2010-03-12 21:14:38 +01:00
|
|
|
@db.put _txn(txn), key.nil? ? nil : key.to_s, val.to_s, 0
|
2010-02-05 19:08:30 +01:00
|
|
|
end
|
|
|
|
end
|
2010-03-12 21:14:38 +01:00
|
|
|
|
|
|
|
def []= key, val
|
|
|
|
put key, val
|
2010-03-11 00:18:38 +01:00
|
|
|
end
|
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def delete key, txn = nil
|
|
|
|
@db.del _txn(txn), key.to_s
|
2010-03-11 00:18:38 +01:00
|
|
|
end
|
|
|
|
alias del delete
|
2010-02-05 19:08:30 +01:00
|
|
|
|
2010-02-02 00:52:25 +01:00
|
|
|
class << self
|
2010-03-12 20:45:06 +01:00
|
|
|
def new *ps, &exe
|
|
|
|
ret = obj = super( *ps)
|
2010-03-12 21:14:38 +01:00
|
|
|
begin ret = exe.call obj
|
2010-02-02 00:52:25 +01:00
|
|
|
ensure
|
2010-03-21 00:39:45 +01:00
|
|
|
SBDB::raise_barrier &obj.method(:sync)
|
|
|
|
SBDB::raise_barrier &obj.method(:close)
|
2010-03-12 20:45:06 +01:00
|
|
|
end if exe
|
|
|
|
ret
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
|
|
|
alias open new
|
|
|
|
end
|
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def _txn txn
|
|
|
|
txn ||= @txn
|
|
|
|
txn && t.bdb_object
|
2010-03-11 00:18:38 +01:00
|
|
|
end
|
|
|
|
|
2010-03-29 15:02:00 +02:00
|
|
|
# Arguments:
|
|
|
|
# * file
|
|
|
|
# * name
|
|
|
|
# * type
|
|
|
|
# * flags
|
|
|
|
# * mode
|
|
|
|
# * env
|
|
|
|
# or: **file**, **opts**. *opts* must be a *::Hash* with keys like above, excluded *file*.
|
2010-02-23 19:39:27 +01:00
|
|
|
def initialize file, *args
|
2010-02-23 20:20:26 +01:00
|
|
|
opts = ::Hash === args.last ? args.pop : {}
|
|
|
|
opts = {:name => args[0], :type => args[1], :flags => args[2], :mode => args[3], :env => args[4]}.update opts
|
2010-02-06 11:47:41 +01:00
|
|
|
#type = BTREE if type == UNKNOWN and (flags & CREATE) == CREATE
|
2010-02-23 19:39:27 +01:00
|
|
|
@home, @db = opts[:env], opts[:env] ? opts[:env].bdb_object.db : Bdb::Db.new
|
2010-02-23 20:20:26 +01:00
|
|
|
opts[:type] = TYPES.index(self.class) || UNKNOWN
|
|
|
|
@db.re_len = opts[:re_len] if opts[:re_len]
|
2010-04-01 13:38:35 +02:00
|
|
|
@txn = nil
|
|
|
|
txn = opts[:txn] # First is the global txn, second only for open.
|
2010-03-07 22:01:05 +01:00
|
|
|
begin
|
2010-03-09 19:09:22 +01:00
|
|
|
@db.open txn && txn.bdb_object, file, opts[:name], opts[:type], opts[:flags] || 0, opts[:mode] || 0
|
2010-02-02 00:52:25 +01:00
|
|
|
rescue Object
|
|
|
|
close
|
|
|
|
raise $!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def each key = nil, val = nil, &exe
|
|
|
|
cursor{|c|c.each key, val, &exe}
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def reverse key = nil, val = nil, &exe
|
|
|
|
cursor{|c|c.reverse key, val, &exe}
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
|
|
|
|
2010-04-03 13:12:57 +02:00
|
|
|
def to_hash key = nil, val = nil
|
2010-04-03 13:09:53 +02:00
|
|
|
ht = {}
|
|
|
|
each key, val, ht.method( :[]=)
|
|
|
|
ht
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
2010-03-11 00:18:38 +01:00
|
|
|
|
|
|
|
def truncate txn = nil
|
|
|
|
@db.truncate _txn(txn)
|
|
|
|
end
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
class Unknown < DB
|
2010-03-12 21:14:38 +01:00
|
|
|
def self.new file, *ps, &exe
|
|
|
|
dbt = super( file, *ps) {|db| db.bdb_object.get_type }
|
|
|
|
TYPES[dbt] ? TYPES[dbt].new( file, *ps, &exe) : super( file, *ps, &exe)
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Btree < DB
|
|
|
|
end
|
2010-02-06 11:50:52 +01:00
|
|
|
TYPES[DB::BTREE] = Btree
|
2010-02-02 00:52:25 +01:00
|
|
|
|
|
|
|
class Hash < DB
|
|
|
|
end
|
2010-02-06 11:50:52 +01:00
|
|
|
TYPES[DB::HASH] = Hash
|
2010-02-02 00:52:25 +01:00
|
|
|
|
2010-03-12 20:45:06 +01:00
|
|
|
module Arrayisch
|
2010-03-12 21:14:38 +01:00
|
|
|
def [] key
|
|
|
|
super [key].pack('I')
|
2010-02-02 15:15:10 +01:00
|
|
|
end
|
|
|
|
|
2010-03-29 11:45:57 +02:00
|
|
|
def []= key, val
|
2010-03-12 21:14:38 +01:00
|
|
|
super [key].pack('I'), val
|
2010-02-02 15:15:10 +01:00
|
|
|
end
|
2010-02-22 16:17:25 +01:00
|
|
|
|
2010-03-12 21:14:38 +01:00
|
|
|
def push val, txn = nil
|
2010-03-29 11:45:57 +02:00
|
|
|
@db.put _txn(txn), "\0\0\0\0", val, Bdb::DB_APPEND
|
2010-02-22 16:17:25 +01:00
|
|
|
end
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
2010-03-12 20:45:06 +01:00
|
|
|
|
|
|
|
class Recno < DB
|
2010-03-29 11:44:04 +02:00
|
|
|
include Arrayisch
|
2010-03-12 20:45:06 +01:00
|
|
|
end
|
2010-02-02 00:52:25 +01:00
|
|
|
Array = Recno
|
2010-02-06 11:50:52 +01:00
|
|
|
TYPES[DB::RECNO] = Recno
|
2010-02-02 00:52:25 +01:00
|
|
|
|
2010-03-21 00:39:45 +01:00
|
|
|
class Queue < DB
|
2010-03-29 11:44:04 +02:00
|
|
|
include Arrayisch
|
2010-03-11 00:18:38 +01:00
|
|
|
def unshift txn = nil
|
|
|
|
@db.get _txn(txn), "\0\0\0\0", nil, Bdb::DB_CONSUME
|
2010-02-05 19:08:30 +01:00
|
|
|
end
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|
2010-02-06 11:50:52 +01:00
|
|
|
TYPES[DB::QUEUE] = Queue
|
2010-02-02 00:52:25 +01:00
|
|
|
end
|