こんにちは。
Tanaka Akira wrote on the <87bro6b9dn.fsf / serein.a02.aist.go.jp>
>read only のときには書き戻さずに .new から読むだけにすればいいのでは?
あ,それでよさそうですね。
こんな感じ。あと,ついでにread onlyのときに[]=, delete()をエラーにする
ようにしています。
*** pstore.rb.orig 2004-02-08 20:30:25.000000000 +0900
--- pstore.rb 2004-02-14 01:24:25.864753912 +0900
***************
*** 35,41 ****
def in_transaction
raise PStore::Error, "not in transaction" unless @transaction
end
! private :in_transaction
def [](name)
in_transaction
--- 35,45 ----
def in_transaction
raise PStore::Error, "not in transaction" unless @transaction
end
! def in_transaction_wr()
! in_transaction()
! raise PStore::Error, "in read-only transaction" if @rdonly
! end
! private :in_transaction, :in_transaction_wr
def [](name)
in_transaction
***************
*** 52,62 ****
self[name]
end
def []=(name, value)
! in_transaction
@table[name] = value
end
def delete(name)
! in_transaction
@table.delete name
end
--- 56,66 ----
self[name]
end
def []=(name, value)
! in_transaction_wr()
@table[name] = value
end
def delete(name)
! in_transaction_wr()
@table.delete name
end
***************
*** 86,112 ****
def transaction(read_only=false)
raise PStore::Error, "nested transaction" if @transaction
begin
@transaction = true
value = nil
! backup = @filename+"~"
! begin
! file = File::open(@filename, read_only ? "rb" : "rb+")
! orig = true
! rescue Errno::ENOENT
! raise if read_only
! file = File::open(@filename, "wb+")
end
! file.flock(read_only ? File::LOCK_SH : File::LOCK_EX)
! if read_only
! @table = Marshal::load(file)
! elsif orig and (content = file.read) != ""
@table = Marshal::load(content)
! size = content.size
! md5 = Digest::MD5.digest(content)
! content = nil # unreference huge data
else
@table = {}
end
begin
catch(:pstore_abort_transaction) do
value = yield(self)
--- 90,127 ----
def transaction(read_only=false)
raise PStore::Error, "nested transaction" if @transaction
begin
+ @rdonly = read_only
+ @abort = false
@transaction = true
value = nil
! new_file = @filename + ".new"
!
! content = nil
! file = File.open(@filename, File::RDWR | File::CREAT)
! if !read_only
! file.flock(File::LOCK_EX)
! commit_new() if FileTest.exist?(new_file)
! content = file.read()
! else
! file.flock(File::LOCK_SH)
! if FileTest.exist?(new_file)
! File.open(new_file) {|fp| content = fp.read()}
! else
! content = file.read()
! end
end
!
! if content != ""
@table = Marshal::load(content)
! if !read_only
! size = content.size
! md5 = Digest::MD5.digest(content)
! end
else
@table = {}
end
+ content = nil # unreference huge data
+
begin
catch(:pstore_abort_transaction) do
value = yield(self)
***************
*** 116,139 ****
raise
ensure
if !read_only and !@abort
! file.rewind
content = Marshal::dump(@table)
if !md5 || size != content.size || md5 != Digest::MD5.digest(content)
! File::copy @filename, backup
! begin
! file.write(content)
! file.truncate(file.pos)
! content = nil # unreference huge data
! rescue
! File::rename backup, @filename if File::exist?(backup)
! raise
! end
! end
! end
! if @abort and !orig
! File.unlink(@filename)
end
- @abort = false
end
ensure
@table = nil
--- 131,147 ----
raise
ensure
if !read_only and !@abort
! tmp_file = @filename + ".tmp"
content = Marshal::dump(@table)
if !md5 || size != content.size || md5 != Digest::MD5.digest(content)
! File.open(tmp_file, "w") {|t|
! t.write(content)
! }
! File.rename(tmp_file, new_file)
! commit_new()
! end
! content = nil # unreference huge data
end
end
ensure
@table = nil
***************
*** 142,147 ****
--- 150,164 ----
end
value
end
+
+ private
+ def commit_new()
+ new_file = @filename + ".new"
+ if !File.copy(new_file, @filename)
+ raise IOError
+ end
+ File.unlink(new_file)
+ end
end
if __FILE__ == $0
--
HORIKAWA Hisashi (in Kanji: 堀川 久)
Netsphere Laboratories http://www.nslabs.jp/