hprevalence 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +18 -0
- data/lib/hprevalence.rb +243 -0
- data/lib/internal/command_logger.rb +98 -0
- data/lib/internal/iomanager.rb +83 -0
- data/lib/internal/object_graph.rb +68 -0
- data/lib/internal/serializer.rb +83 -0
- data/lib/internal/store_manager.rb +74 -0
- data/lib/transparent.rb +218 -0
- data/rake.rb +4 -0
- data/rakefile.rb +62 -0
- data/test/abstract_hprevalence_testcase.rb +26 -0
- data/test/command_logger_test.rb +39 -0
- data/test/default_model_serializer_test.rb +65 -0
- data/test/dvd_store_model.rb +57 -0
- data/test/file_io_manager_test.rb +129 -0
- data/test/natural_object_model_test.rb +119 -0
- data/test/simple_engine_test.rb +79 -0
- data/test/task_model.rb +74 -0
- data/test/transparent_module_test.rb +95 -0
- metadata +54 -0
data/README
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
Thanks for using HPrevalence!
|
3
|
+
|
4
|
+
Don't forget:
|
5
|
+
|
6
|
+
- You'll need RubyGems to install it:
|
7
|
+
Grab it http://rubygems.rubyforge.org
|
8
|
+
|
9
|
+
And HPrevalence depends on
|
10
|
+
|
11
|
+
- Guid
|
12
|
+
http://guid.rubyforge.org
|
13
|
+
|
14
|
+
- Rake (if you want to execute the test cases)
|
15
|
+
http://rake.rubyforge.org
|
16
|
+
|
17
|
+
|
18
|
+
Enjoy!
|
data/lib/hprevalence.rb
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
require 'guid'
|
4
|
+
require 'transparent'
|
5
|
+
require 'internal/command_logger'
|
6
|
+
require 'internal/iomanager'
|
7
|
+
require 'internal/serializer'
|
8
|
+
require 'internal/store_manager'
|
9
|
+
|
10
|
+
module HPrevalence
|
11
|
+
|
12
|
+
#
|
13
|
+
class EngineBuilder
|
14
|
+
|
15
|
+
def self.build( target_dir, &system_init )
|
16
|
+
system = system_init.call
|
17
|
+
SimpleEngine.new( target_dir, system )
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.build_transparent( target_dir, &system_init )
|
21
|
+
system = system_init.call
|
22
|
+
TransparentEngine.new( target_dir, system )
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
class SimpleEngine
|
29
|
+
|
30
|
+
attr_reader :system, :target_dir
|
31
|
+
|
32
|
+
def initialize( target_dir, system, store_manager = StorageManager.new(target_dir) )
|
33
|
+
@lock = Mutex.new
|
34
|
+
@target_dir, @system, @store_manager = target_dir, system, store_manager
|
35
|
+
@system = @store_manager.restore( system() )
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute_command( command )
|
39
|
+
raise 'Invalid command' unless command.respond_to?( :execute )
|
40
|
+
@lock.synchronize {
|
41
|
+
@store_manager.store( command )
|
42
|
+
return command.execute( @system )
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def close
|
47
|
+
@store_manager.close
|
48
|
+
end
|
49
|
+
|
50
|
+
def take_snapshot
|
51
|
+
@lock.synchronize {
|
52
|
+
@store_manager.take_snapshot @system
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Holds only one system
|
60
|
+
#
|
61
|
+
class TransparentEngine < SimpleEngine
|
62
|
+
@@engines = Hash.new()
|
63
|
+
@@class_lock = Mutex.new
|
64
|
+
|
65
|
+
attr_reader :engine_id
|
66
|
+
|
67
|
+
def initialize( target_dir, system )
|
68
|
+
@proxies_lock = Mutex.new
|
69
|
+
@engine_id = Guid.new()
|
70
|
+
|
71
|
+
TransparentEngine.register_engine( self )
|
72
|
+
|
73
|
+
@proxies = []
|
74
|
+
add_engine_id_method( system )
|
75
|
+
store_manager = TransparentStorageManager.new(self, target_dir)
|
76
|
+
within_engine {
|
77
|
+
@proxied_system = HPrevalence::Transparent::TransparentProxy.new( system )
|
78
|
+
}
|
79
|
+
|
80
|
+
super( target_dir, system, store_manager )
|
81
|
+
end
|
82
|
+
|
83
|
+
def system
|
84
|
+
@proxied_system
|
85
|
+
end
|
86
|
+
|
87
|
+
def close
|
88
|
+
super
|
89
|
+
TransparentEngine.unregister_engine( self )
|
90
|
+
end
|
91
|
+
|
92
|
+
def take_snapshot
|
93
|
+
@lock.synchronize {
|
94
|
+
begin
|
95
|
+
Thread.current[:references] = Hash.new
|
96
|
+
within_engine {
|
97
|
+
@store_manager.take_snapshot @proxied_system
|
98
|
+
}
|
99
|
+
ensure
|
100
|
+
Thread.current[:references] = nil
|
101
|
+
end
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def execute_command(command)
|
106
|
+
super(command)
|
107
|
+
end
|
108
|
+
|
109
|
+
def register_proxy(proxy)
|
110
|
+
# TODO: Synchronization here?
|
111
|
+
@proxies << proxy
|
112
|
+
@proxies.length - 1
|
113
|
+
end
|
114
|
+
|
115
|
+
def proxy_by_id( id, related_symbol = nil, parent_proxy_id = nil )
|
116
|
+
p = @proxies[ id ]
|
117
|
+
return p unless p.nil?
|
118
|
+
if !related_symbol.nil? && !parent_proxy_id.nil?
|
119
|
+
return create_nested_proxy( parent_proxy_id, related_symbol )
|
120
|
+
end
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
124
|
+
def create_nested_proxy( parent_proxy_id, related_symbol )
|
125
|
+
@proxies_lock.synchronize {
|
126
|
+
parent_proxy = proxy_by_id( parent_proxy_id )
|
127
|
+
target = parent_proxy.target
|
128
|
+
nested_target = target.send( related_symbol )
|
129
|
+
new_proxy = HPrevalence::Transparent::NestedTransparentProxy.new( nested_target, related_symbol, parent_proxy_id )
|
130
|
+
target._set_proxy( related_symbol, new_proxy )
|
131
|
+
return new_proxy
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def within_engine()
|
136
|
+
begin
|
137
|
+
Thread.current[:engine] = self
|
138
|
+
yield
|
139
|
+
ensure
|
140
|
+
Thread.current[:engine] = nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def restore(proxy)
|
145
|
+
proxy.engine_id = @engine_id
|
146
|
+
p = proxy_by_id(proxy.proxy_id)
|
147
|
+
if (p.nil?)
|
148
|
+
proxy.proxy_id = register_proxy(proxy)
|
149
|
+
p = proxy
|
150
|
+
end
|
151
|
+
p
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.create_nested_proxy( parent_proxy_id, symbol, engine_id )
|
155
|
+
within_engine( engine_id ) { |engine|
|
156
|
+
engine.create_nested_proxy( parent_proxy_id, symbol )
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.within_engine( engine_id )
|
161
|
+
engine = @@engines[ engine_id ]
|
162
|
+
raise 'Engine not found' if engine.nil?
|
163
|
+
begin
|
164
|
+
# puts 'engine>'
|
165
|
+
Thread.current[:engine] = engine
|
166
|
+
yield(engine)
|
167
|
+
ensure
|
168
|
+
Thread.current[:engine] = nil
|
169
|
+
# puts 'engine<'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.current()
|
174
|
+
engine = Thread.current[:engine]
|
175
|
+
|
176
|
+
if block_given?
|
177
|
+
# puts 'engine.current'
|
178
|
+
raise 'Engine not found' if engine.nil?
|
179
|
+
yield( engine )
|
180
|
+
# puts 'end.current'
|
181
|
+
else
|
182
|
+
return engine
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
protected
|
187
|
+
|
188
|
+
def self.register_engine( engine )
|
189
|
+
@@class_lock.synchronize {
|
190
|
+
@@engines[engine.engine_id] = engine
|
191
|
+
}
|
192
|
+
end
|
193
|
+
|
194
|
+
def self.unregister_engine( engine )
|
195
|
+
@@class_lock.synchronize {
|
196
|
+
@@engines.delete(engine.engine_id)
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_engine_id_method( system )
|
201
|
+
temp_id = @engine_id
|
202
|
+
system.instance_eval {
|
203
|
+
@engine_id = temp_id
|
204
|
+
}
|
205
|
+
# (class << system; self;end).class_eval do
|
206
|
+
# define_method(:_engine_id) { @engine_id }
|
207
|
+
# end
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
class PrevalenceService
|
213
|
+
attr_reader :engine
|
214
|
+
|
215
|
+
def self.create_service( snapshot_interval = 60 * 60 * 1000, &engine_init )
|
216
|
+
engine = engine_init.call
|
217
|
+
raise 'Engine not created' if engine.nil?
|
218
|
+
PrevalenceService.new( engine, snapshot_interval )
|
219
|
+
end
|
220
|
+
|
221
|
+
def system
|
222
|
+
@engine.system
|
223
|
+
end
|
224
|
+
|
225
|
+
protected
|
226
|
+
|
227
|
+
def initialize( engine, snapshot_interval )
|
228
|
+
@engine = engine
|
229
|
+
@snapshot_interval = snapshot_interval
|
230
|
+
end
|
231
|
+
|
232
|
+
def start_snapshot_thread
|
233
|
+
Thread.new(self) {
|
234
|
+
while true
|
235
|
+
sleep(@snapshot_interval)
|
236
|
+
engine.take_snapshot
|
237
|
+
end
|
238
|
+
}
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
|
2
|
+
class BinaryCommandSerializer
|
3
|
+
|
4
|
+
def initialize( io )
|
5
|
+
raise 'Invalid stream' if io.nil?
|
6
|
+
@io = io
|
7
|
+
@io.binmode
|
8
|
+
# register_finalize()
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(command)
|
12
|
+
raise 'Invalid command' if command.nil?
|
13
|
+
Marshal.dump( command, @io )
|
14
|
+
@io.flush
|
15
|
+
@io.fsync
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.restore_from_io( io, system )
|
19
|
+
# Theorically this should work and its more elegant than the current version
|
20
|
+
# Marshal.load( io ) { |command|
|
21
|
+
# command.execute( system )
|
22
|
+
# }
|
23
|
+
while( !io.eof? )
|
24
|
+
command = Marshal.load( io )
|
25
|
+
command.execute( system )
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def close
|
30
|
+
@io.close
|
31
|
+
# unregister_finalize
|
32
|
+
end
|
33
|
+
#
|
34
|
+
# protected
|
35
|
+
#
|
36
|
+
# def register_finalize
|
37
|
+
# ObjectSpace.define_finalizer( self ) {
|
38
|
+
# |logger|
|
39
|
+
# logger.close
|
40
|
+
# }
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def unregister_finalize
|
44
|
+
# ObjectSpace.undefine_finalizer( self )
|
45
|
+
# end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class CommandLogger
|
50
|
+
|
51
|
+
Logger_Extension = 'commandlog'
|
52
|
+
|
53
|
+
attr_reader :current_file_name
|
54
|
+
|
55
|
+
def initialize( iomanager )
|
56
|
+
@iomanager = iomanager
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_command_store()
|
60
|
+
stream = @iomanager.create_new_stream( Logger_Extension )
|
61
|
+
@current_file_name = stream.full_name
|
62
|
+
BinaryCommandSerializer.new( stream )
|
63
|
+
end
|
64
|
+
|
65
|
+
def log_files
|
66
|
+
@iomanager.list( Logger_Extension )
|
67
|
+
end
|
68
|
+
|
69
|
+
# removes all command_logs as a snapshot has been taken
|
70
|
+
def reset_commands()
|
71
|
+
streams = @iomanager.obtain_ordered_read_streams( Logger_Extension )
|
72
|
+
|
73
|
+
streams.each do |stream|
|
74
|
+
stream.close
|
75
|
+
File.delete stream.full_name
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def restore( system )
|
81
|
+
streams = @iomanager.obtain_ordered_read_streams( Logger_Extension )
|
82
|
+
|
83
|
+
begin
|
84
|
+
|
85
|
+
streams.each do |stream|
|
86
|
+
BinaryCommandSerializer.restore_from_io( stream, system )
|
87
|
+
end
|
88
|
+
|
89
|
+
ensure
|
90
|
+
streams.each do |stream|
|
91
|
+
stream.close
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class FileIOManager
|
4
|
+
|
5
|
+
attr_reader :positions, :target_dir
|
6
|
+
|
7
|
+
def initialize( target_dir, positions = 12 )
|
8
|
+
@target_dir, @positions = target_dir, positions
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_new_stream( extension )
|
12
|
+
file_name = obtain_next_available( extension )
|
13
|
+
create_write_stream( file_name )
|
14
|
+
end
|
15
|
+
|
16
|
+
def list( extension )
|
17
|
+
unless File.exist?( @target_dir )
|
18
|
+
return []
|
19
|
+
end
|
20
|
+
dir = File.join( @target_dir, "*.#{extension}" )
|
21
|
+
valid_entries = Dir.entries( @target_dir ).select do |entry|
|
22
|
+
entry =~ /^\d{#{positions}}\.#{extension}$/
|
23
|
+
end
|
24
|
+
valid_entries.sort
|
25
|
+
end
|
26
|
+
|
27
|
+
def obtain_ordered_read_streams( extension )
|
28
|
+
streams = []
|
29
|
+
|
30
|
+
list( extension ).each do |file|
|
31
|
+
file_name = File.join( @target_dir, file )
|
32
|
+
streams << create_read_stream( file_name )
|
33
|
+
end
|
34
|
+
|
35
|
+
streams
|
36
|
+
end
|
37
|
+
|
38
|
+
def obtain_latest_read_stream( extension )
|
39
|
+
files = list( extension )
|
40
|
+
return nil if files.length == 0
|
41
|
+
|
42
|
+
file_name = File.join( @target_dir, files.max )
|
43
|
+
create_read_stream( file_name )
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def create_read_stream( file_name )
|
49
|
+
file = File.new( file_name, "rb" )
|
50
|
+
add_helper_methods( file, file_name )
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_write_stream( file_name )
|
54
|
+
file = File.new( file_name, "wb" )
|
55
|
+
add_helper_methods( file, file_name )
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_helper_methods( stream, file_name )
|
59
|
+
(class << stream; self; end).class_eval do
|
60
|
+
define_method(:full_name) { file_name }
|
61
|
+
define_method(:basename) { File.basename(file_name) }
|
62
|
+
end
|
63
|
+
stream
|
64
|
+
end
|
65
|
+
|
66
|
+
def obtain_hightest_num( extension )
|
67
|
+
val = 0
|
68
|
+
list( extension ).each do |file|
|
69
|
+
new_val = file.slice( 0, positions ).to_i
|
70
|
+
if new_val > val
|
71
|
+
val = new_val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
val
|
75
|
+
end
|
76
|
+
|
77
|
+
def obtain_next_available( extension )
|
78
|
+
val = obtain_hightest_num( extension )
|
79
|
+
sprintf("%s/%0#{positions}d.%s", @target_dir, val + 1, extension)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
class ObjectGraph
|
3
|
+
|
4
|
+
def initialize()
|
5
|
+
@root = nil
|
6
|
+
@registry = Hash.new()
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.build( node )
|
10
|
+
graph = ObjectGraph.new()
|
11
|
+
graph.root = node
|
12
|
+
graph
|
13
|
+
end
|
14
|
+
|
15
|
+
def root=( node )
|
16
|
+
@root = GraphItem.new( self, node )
|
17
|
+
end
|
18
|
+
|
19
|
+
def root
|
20
|
+
@root.object
|
21
|
+
end
|
22
|
+
|
23
|
+
def object_reference( var )
|
24
|
+
graph_item = @registry[ var ]
|
25
|
+
if (graph_item.nil?)
|
26
|
+
graph_item = GraphItem.new( self, var )
|
27
|
+
@registry[ var ] = graph_item
|
28
|
+
end
|
29
|
+
graph_item
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class GraphItem
|
35
|
+
|
36
|
+
def initialize( graph, node )
|
37
|
+
@instance_vars = Hash.new
|
38
|
+
@node_type = node.class
|
39
|
+
|
40
|
+
node.instance_variables.each do |var|
|
41
|
+
name = var.slice(1, var.length - 1)
|
42
|
+
@instance_vars[ name ] = graph.object_reference( node.instance_eval(var) )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def object
|
47
|
+
obj = @node_type.allocate
|
48
|
+
restore_instance_vars obj
|
49
|
+
obj
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def restore_instance_vars(obj)
|
55
|
+
@instance_vars.each do |name, value|
|
56
|
+
|
57
|
+
var = value.object
|
58
|
+
|
59
|
+
setter = name + "="
|
60
|
+
if obj.respond_to?(setter)
|
61
|
+
obj.__send__(setter, var)
|
62
|
+
else
|
63
|
+
obj.instance_eval("@#{ name } = var")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
class DefaultModelSerializer
|
3
|
+
|
4
|
+
Snapshot_Extension = 'snapshot'
|
5
|
+
|
6
|
+
def initialize( iomanager )
|
7
|
+
@iomanager = iomanager
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump( object_model )
|
11
|
+
begin
|
12
|
+
stream = @iomanager.create_new_stream( Snapshot_Extension )
|
13
|
+
Marshal.dump( object_model, stream )
|
14
|
+
ensure
|
15
|
+
stream.close
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def load()
|
20
|
+
object_model = nil
|
21
|
+
stream = @iomanager.obtain_latest_read_stream( Snapshot_Extension )
|
22
|
+
return nil if stream.nil?
|
23
|
+
|
24
|
+
begin
|
25
|
+
object_model = Marshal.load( stream )
|
26
|
+
ensure
|
27
|
+
stream.close
|
28
|
+
end
|
29
|
+
|
30
|
+
object_model
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
#class SmartModelSerializer
|
36
|
+
#
|
37
|
+
# Snapshot_Extension = 'ssnapshot'
|
38
|
+
#
|
39
|
+
# def initialize( iomanager )
|
40
|
+
# @iomanager = iomanager
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def dump( object_model )
|
44
|
+
#
|
45
|
+
# begin
|
46
|
+
# stream = @iomanager.create_new_stream( Snapshot_Extension )
|
47
|
+
# graph = ObjectGraph.build( object_model )
|
48
|
+
# write_object_tree( stream, graph )
|
49
|
+
# ensure
|
50
|
+
# stream.close
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def load()
|
56
|
+
#
|
57
|
+
# object_model = nil
|
58
|
+
#
|
59
|
+
# begin
|
60
|
+
# stream = @iomanager.obtain_latest_read_stream( Snapshot_Extension )
|
61
|
+
# graph = read_object_tree( stream )
|
62
|
+
# object_model = graph.root
|
63
|
+
# ensure
|
64
|
+
# stream.close
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# object_model
|
68
|
+
#
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# protected
|
72
|
+
#
|
73
|
+
# def write_object_tree( stream, object )
|
74
|
+
# Marshal.dump( object, stream )
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def read_object_tree( stream )
|
78
|
+
# Marshal.load( stream )
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
#end
|
82
|
+
|
83
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
module HPrevalence
|
3
|
+
|
4
|
+
class StorageManager
|
5
|
+
|
6
|
+
def initialize( target_dir, iomanager = FileIOManager.new(target_dir), logger = CommandLogger.new(iomanager), model_serializer = DefaultModelSerializer.new(iomanager) )
|
7
|
+
@target_dir, @model_serializer = target_dir, model_serializer
|
8
|
+
@logger = logger
|
9
|
+
@comand_store = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def restore( system )
|
13
|
+
system = restore_snapshot( system )
|
14
|
+
restore_commands( system )
|
15
|
+
system
|
16
|
+
end
|
17
|
+
|
18
|
+
def store( command )
|
19
|
+
ensure_command_store
|
20
|
+
@comand_store << command
|
21
|
+
end
|
22
|
+
|
23
|
+
def take_snapshot( system )
|
24
|
+
@model_serializer.dump( system )
|
25
|
+
close()
|
26
|
+
@logger.reset_commands
|
27
|
+
end
|
28
|
+
|
29
|
+
def close
|
30
|
+
@comand_store.close unless @comand_store.nil?
|
31
|
+
@comand_store = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def ensure_command_store
|
37
|
+
@comand_store ||= @logger.create_command_store()
|
38
|
+
end
|
39
|
+
|
40
|
+
def restore_commands( system )
|
41
|
+
@logger.restore( system )
|
42
|
+
end
|
43
|
+
|
44
|
+
def restore_snapshot( system )
|
45
|
+
system_new = @model_serializer.load
|
46
|
+
if !system_new.nil?
|
47
|
+
system = system_new
|
48
|
+
end
|
49
|
+
system
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
#
|
56
|
+
#
|
57
|
+
class TransparentStorageManager < StorageManager
|
58
|
+
|
59
|
+
def initialize( engine, target_dir, iomanager = FileIOManager.new(target_dir), logger = CommandLogger.new(iomanager), model_serializer = DefaultModelSerializer.new(iomanager) )
|
60
|
+
super( target_dir, iomanager, logger, model_serializer )
|
61
|
+
@engine = engine
|
62
|
+
end
|
63
|
+
|
64
|
+
def restore( system )
|
65
|
+
@engine.within_engine {
|
66
|
+
system = restore_snapshot( system )
|
67
|
+
restore_commands( system )
|
68
|
+
}
|
69
|
+
system
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|