hprevalence 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|