けいじゅ@日本ラショナルソフトウェアです.
pstoreに関してですが, transactionをコミットしたあとでも @table の参照
が残ったままですよね? marshalした後, @table = nil とした方がよかないで
すか? 今のままだと, @tableの内容がGCの対象になりません.
そんでもって, いいの考えました. キャッシュ機能付きPStoreです.
コミットした後, @tableの参照しているインスタンスをWeakRefを用いて保存
しておいて, 次にtransactionを開始した時に, GCされずに残っていたらそれ
をそのまま使う方法です.
こうすると, 読み込みのコストが下がる可能性が高くなっるのでよいと思いま
せん?
-- ここから
#
# How to use:
#
# db = PStoreWC.new("/tmp/foo")
# db.transaction do
# p db.roots
# ary = db["root"] = [1,2,3,4]
# ary[0] = [1,1.5]
# end
# db.transaction do
# p db["root"]
# end
require "pstore"
require "weakref"
class PStoreWC < PStore
def initialize(file)
super
@cache = nil
end
def transaction
raise PStore::Error, "nested transaction" if @transaction
begin
@transaction = true
value = file = nil
if @cache and @cache.weakref_alive?
@table = @cache[]
else
begin
File::open(@filename, "r") do |file|
@table = Marshal.load(file)
end
rescue Errno::ENOENT
@table = {}
end
end
begin
catch(:pstore_abort_transaction) do
value = yield(self)
end
rescue Exception
@abort = true
raise
ensure
unless @abort
begin
File::rename @filename, @filename+"~"
rescue Errno::ENOENT
no_orig = true
end
begin
File::open(@filename, "w") do |file|
Marshal::dump(@table, file)
@cache = WeakRef.new(@table)
end
rescue
File::rename @filename+"~", @filename unless no_orig
end
end
@abort = false
end
ensure
@transaction = false
end
value
end
end
PSWC = PStoreWC
if __FILE__ == $0
db = PStoreWC.new("/tmp/foo")
db.transaction do
p db.roots
ary = db["root"] = [1,2,3,4]
ary[0] = [1,1.5]
end
db.transaction do
p db["root"]
end
ObjectSpace.garbage_collect
db.transaction do
p db["root"]
end
end
__
..............................石塚 圭樹@日本ラショナルソフトウェア...
----------------------------------->> e-mail: keiju / rational.com <<---