gdbm: ラッパーその2

さすがに読み取り時も排他ロックをかけるのはまずそうなので、読み取り時は共有ロックをかけるようにしてみる。

require 'gdbm'

class GDBMStore
  @@READABLES = [
    :[],
    :each,
    :each_key,
    :each_pair,
    :each_value,
    :empty?,
    :fetch,
    :has_key?,
    :has_value?,
    :include?,
    :index,
    :indexes,
    :indices,
    :invert,
    :key?,
    :keys,
    :length,
    :member?,
    :size,
    :to_a,
    :to_hash,
    :value?,
    :values,
  ]

  def initialize(dbname)
    @dbfile = File.expand_path(dbname)
    @lockfile = "#{File.dirname(@dbfile)}/lock_#{File.basename(@dbfile)}"
  end

  def with_lock_sh
    File.open(@lockfile, 'a') {|f|
      f.flock(File::LOCK_SH)
      GDBM.open(@dbfile) {|dbm| yield(dbm) }
    }
  end

  def with_lock_ex
    File.open(@lockfile, 'a') {|f|
      f.flock(File::LOCK_EX)
      GDBM.open(@dbfile) {|dbm| yield(dbm) }
    }
  end

  def method_missing(name, *args, &block)
    return super(name, *args, &block) unless GDBM.method_defined?(name)

    if @@READABLES.include? name
      with_lock_sh {|dbm| dbm.send(name, *args, &block) }
    else
      with_lock_ex {|dbm| dbm.send(name, *args, &block) }
    end
  end
end

しかし、コードがださい!
読み取り用メソッドを羅列してることこなんか。
似たようなコード部分があるのも気になる。
うぅ…