summaryrefslogtreecommitdiff
path: root/lib/yaml/store.rb
blob: 2e74b27221f32f7cde5af259c4af7a487d71bb7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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.shift)
            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