summaryrefslogtreecommitdiff
path: root/lib/yaml/store.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/yaml/store.rb')
-rw-r--r--lib/yaml/store.rb75
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/yaml/store.rb b/lib/yaml/store.rb
new file mode 100644
index 0000000000..b2924b0660
--- /dev/null
+++ b/lib/yaml/store.rb
@@ -0,0 +1,75 @@
+#
+# YAML::Store
+#
+require 'yaml'
+require 'pstore'
+
+module YAML
+
+ class Store < PStore
+ #
+ # Constructor
+ #
+ def initialize( *o )
+ @opt = YAML::DEFAULTS.dup
+ if String === o.first
+ super(o.pop)
+ end
+ if o.last.is_a? Hash
+ @opt.update(o.pop)
+ end
+ 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
+
+end