@m_seki の

I like ruby tooから引っ越し

TokyoCabinet

qdbmつながりで試してみた。
APIが例外は自分であげる作戦なので、注意。
並行動作はこれから試します。複数のプロセスと、マルチスレッドで。
一つのBDBオブジェクトで違うファイルをopen, close, open, closeするときに、ちょっと怪しい動作をしたのでBDBインスタンスを毎回生成するようにしてみました。コストはどうなんだろ。

require 'monitor'
require 'tokyocabinet'

class TokyoNano
  include MonitorMixin
  include TokyoCabinet

  def initialize(name)
    super()
    @name = name
  end

  def add(key, value, bdb=nil)
    if bdb
      bdb.putdup(key, value) || raise(bdb.errmsg(bdb.ecode))
    else
      open {|b| add(key, value, b)}
    end
  end

  def get(key, bdb=nil)
    if bdb
      bdb.getlist(key)
    else
      open(TokyoCabinet::BDB::OREADER) {|b| self.get(key, b)}
    end
  end

  def take(key, bdb=nil)
    if bdb
      value = bdb.getlist(key)
      bdb.outlist(key)
      value
    else
      open {|b| take(key, b)}
    end
  end

  def open(mode = BDB::OWRITER | BDB::OCREAT)
    synchronize do
      bdb = BDB.new
      begin
        bdb.open(@name, mode) || raise(bdb.errmsg(bdb.ecode))
        yield(bdb)
      ensure
        bdb.close
      end
    end
  end
end

if __FILE__ == $0
  require 'pp'

  nano = TokyoNano.new('tokyo_nano.bdb')
  if ARGV[0] == '-i'
    ARGV.shift
    nano.open do |bdb|
      while line = gets
        line.scan(/\w+/) do |x|
          nano.add(x, Marshal.dump([ARGF.filename, ARGF.lineno]), bdb)
        end
      end
    end
  else
    pp nano.get(ARGV.shift).collect {|x| Marshal.load(x)}
  end
end