diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-01 14:15:38 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-01 14:15:38 +0000 |
commit | 7800d8ad76bfda9884f5127c576ba08b1fe82583 (patch) | |
tree | 60f53b0878437539143899edaaa35a54635b3182 | |
parent | c7bd86ed15eb4baf2dcb9a7b732891de4619d88a (diff) |
* lib/pstore.rb (transaction): safer backup scheme. [ruby-list:39102]
* lib/pstore.rb (commit_new): use FileUtils.copy_stream for Cygwin.
[ruby-dev:23157]
* lib/pstore.rb (transaction): allow overriding dump and load.
[ruby-dev:23567]
* lib/pstore.rb (PStore#transaction): get rid of opening in write mode
when read only transaction. [ruby-dev:23842]
* lib/yaml/store.rb: follow lib/pstore.rb's change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6562 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | lib/pstore.rb | 98 | ||||
-rw-r--r-- | lib/yaml/store.rb | 84 |
3 files changed, 100 insertions, 103 deletions
@@ -1,3 +1,18 @@ +Thu Jul 1 23:15:29 2004 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * lib/pstore.rb (transaction): safer backup scheme. [ruby-list:39102] + + * lib/pstore.rb (commit_new): use FileUtils.copy_stream for Cygwin. + [ruby-dev:23157] + + * lib/pstore.rb (transaction): allow overriding dump and load. + [ruby-dev:23567] + + * lib/pstore.rb (PStore#transaction): get rid of opening in write mode + when read only transaction. [ruby-dev:23842] + + * lib/yaml/store.rb: follow lib/pstore.rb's change. + Thu Jul 1 18:36:08 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * ext/tk/lib/tcltklib : bug fix @@ -79,13 +94,13 @@ Thu Jul 1 03:16:09 2004 GOTOU Yuuzou <gotoyuzo@notwork.org> * ext/openssl/ossl_ssl.c (ossl_ssl_read): take optional second argument to specify a string to be written. - + * ext/openssl/lib/openssl/buffering.rb (OpenSSL::Buffering#read): take optional second argument to specify a string to be written. - + * ext/openssl/lib/openssl/buffering.rb (OpenSSL::Buffering#gets): refine regexp for end-of-line. - + * ext/opnessl/lib/openssl/ssl.rb (OpenSSL::SSL::SocketForwarder#listen): fix typo. diff --git a/lib/pstore.rb b/lib/pstore.rb index 93795495fc..c4c6dd56a5 100644 --- a/lib/pstore.rb +++ b/lib/pstore.rb @@ -12,7 +12,7 @@ # p db["root"] # end -require "ftools" +require "fileutils" require "digest/md5" class PStore @@ -35,7 +35,11 @@ class PStore def in_transaction raise PStore::Error, "not in transaction" unless @transaction end - private :in_transaction + 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,11 +56,11 @@ class PStore self[name] end def []=(name, value) - in_transaction + in_transaction_wr() @table[name] = value end def delete(name) - in_transaction + in_transaction_wr() @table.delete name end @@ -86,27 +90,35 @@ class PStore def transaction(read_only=false) raise PStore::Error, "nested transaction" if @transaction begin + @rdonly = read_only + @abort = false @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+") + new_file = @filename + ".new" + + content = nil + unless read_only + file = File.open(@filename, File::RDWR | File::CREAT) + file.flock(File::LOCK_EX) + commit_new(file) if FileTest.exist?(new_file) + content = file.read() + else + file = File.open(@filename, File::RDONLY) + file.flock(File::LOCK_SH) + content = (File.read(new_file) rescue file.read()) 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 + + if content != "" + @table = 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,24 +128,17 @@ class PStore raise ensure if !read_only and !@abort - file.rewind - content = Marshal::dump(@table) + tmp_file = @filename + ".tmp" + content = 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) + File.open(tmp_file, "w") {|t| + t.write(content) + } + File.rename(tmp_file, new_file) + commit_new(file) + end + content = nil # unreference huge data end - @abort = false end ensure @table = nil @@ -142,6 +147,29 @@ class PStore end value end + + def dump(table) + Marshal::dump(table) + end + + def load(content) + Marshal::load(content) + end + + def load_file(file) + Marshal::load(file) + end + + private + def commit_new(f) + f.truncate(0) + f.rewind + new_file = @filename + ".new" + File.open(new_file) do |nf| + FileUtils.copy_stream(nf, f) + end + File.unlink(new_file) + end end if __FILE__ == $0 diff --git a/lib/yaml/store.rb b/lib/yaml/store.rb index 2e74b27221..2ffa9554b9 100644 --- a/lib/yaml/store.rb +++ b/lib/yaml/store.rb @@ -4,72 +4,26 @@ require 'yaml' require 'pstore' -module YAML +class YAML::Store < PStore + def initialize( *o ) + @opt = YAML::DEFAULTS.dup + if String === o.first + super(o.shift) + end + if o.last.is_a? Hash + @opt.update(o.pop) + end + end - class Store < PStore - # - # Constructor - # - def initialize( *o ) - @opt = YAML::DEFAULTS.dup - if String === o.first - super(o.shift) - end - if o.last.is_a? Hash - @opt.update(o.pop) - end - end + def dump(table) + @table.to_yaml(@opt) + end - # - # Override Pstore#transaction - # - def transaction - raise YAML::Error, "nested transaction" if @transaction - raise YAML::Error, "no filename for transaction" unless @filename - begin - @transaction = true - value = nil - backup = @filename+"~" - if File::exist?(@filename) - file = File::open(@filename, "rb+") - orig = true - else - @table = {} - file = File::open(@filename, "wb+") - file.write( @table.to_yaml( @opt ) ) - end - file.flock(File::LOCK_EX) - if orig - File::copy @filename, backup - @table = YAML::load( file ) - end - begin - catch(:pstore_abort_transaction) do - value = yield(self) - end - rescue Exception - @abort = true - raise - ensure - unless @abort - begin - file.rewind - file.write( @table.to_yaml( @opt ) ) - file.truncate(file.pos) - rescue - File::rename backup, @filename if File::exist?(backup) - raise - end - end - @abort = false - end - ensure - @table = nil - @transaction = false - file.close if file - end - value - end - end + def load(content) + YAML::load(content) + end + def load_file(file) + YAML::load(file) + end end |