hprevalence 0.1.1 → 0.2.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.
@@ -1,29 +1,29 @@
1
1
 
2
2
  require 'thread'
3
- require 'guid'
4
- require 'transparent'
5
3
  require 'internal/command_logger'
6
4
  require 'internal/iomanager'
7
5
  require 'internal/serializer'
8
6
  require 'internal/store_manager'
7
+ require 'internal/marshallers/default'
9
8
 
10
9
  module HPrevalence
11
10
 
12
11
  #
13
12
  class EngineBuilder
14
13
 
15
- def self.build( target_dir, &system_init )
16
- ensure_dir( target_dir )
17
- system = system_init.call
18
- SimpleEngine.new( target_dir, system )
19
- end
20
-
21
- def self.build_transparent( target_dir, &system_init )
14
+ def self.build(
15
+ target_dir,
16
+ marshaller = DefaultMarshaller.new(),
17
+ iomanager = FileIOManager.new(target_dir),
18
+ model_serializer = DefaultModelSerializer.new(iomanager, marshaller),
19
+ &system_init )
20
+
22
21
  ensure_dir( target_dir )
23
22
  system = system_init.call
24
- TransparentEngine.new( target_dir, system )
23
+ raise 'System nil ?' if system.nil?
24
+ SimpleEngine.new( target_dir, system, iomanager, marshaller, model_serializer )
25
25
  end
26
-
26
+
27
27
  private
28
28
 
29
29
  def self.ensure_dir( dir )
@@ -34,12 +34,18 @@ module HPrevalence
34
34
 
35
35
  end
36
36
 
37
- #
37
+ #
38
38
  class SimpleEngine
39
-
40
39
  attr_reader :system, :target_dir
41
40
 
42
- def initialize( target_dir, system, store_manager = StorageManager.new(target_dir) )
41
+ def initialize(
42
+ target_dir,
43
+ system,
44
+ iomanager = FileIOManager.new(target_dir),
45
+ marshaller = DefaultMarshaller.new(),
46
+ model_serializer = DefaultModelSerializer.new(iomanager, marshaller),
47
+ store_manager = StorageManager.new(target_dir, iomanager, marshaller, model_serializer) )
48
+
43
49
  @lock = Mutex.new
44
50
  @target_dir, @system, @store_manager = target_dir, system, store_manager
45
51
  @system = @store_manager.restore( system() )
@@ -48,8 +54,10 @@ module HPrevalence
48
54
  def execute_command( command )
49
55
  raise 'Invalid command' unless command.respond_to?( :execute )
50
56
  @lock.synchronize {
57
+ set_time_if_requested(command)
58
+ result = command.execute( @system )
51
59
  @store_manager.store( command )
52
- return command.execute( @system )
60
+ result
53
61
  }
54
62
  end
55
63
 
@@ -63,174 +71,12 @@ module HPrevalence
63
71
  }
64
72
  end
65
73
 
66
- end
67
-
68
- #
69
- #
70
- class TransparentEngine < SimpleEngine
71
- @@engines = Hash.new()
72
- @@class_lock = Mutex.new
73
-
74
- attr_reader :engine_id
75
-
76
- def initialize( target_dir, system )
77
- @proxies_lock = Mutex.new
78
- @engine_id = Guid.new()
79
-
80
- TransparentEngine.register_engine( self )
81
-
82
- @proxies = Hash.new
83
- add_engine_id_method( system )
84
- store_manager = TransparentStorageManager.new(self, target_dir)
85
- within_engine {
86
- @proxied_system = HPrevalence::Transparent::TransparentProxy.new( system, Guid.from_s('00000000-0000-0000-0000-000000000000') )
87
- }
88
-
89
- super( target_dir, system, store_manager )
90
- end
91
-
92
- def system
93
- @proxied_system
94
- end
95
-
96
- def close
97
- super
98
- TransparentEngine.unregister_engine( self )
99
- end
100
-
101
- def take_snapshot
102
- @lock.synchronize {
103
- begin
104
- Thread.current[:references] = Hash.new
105
- within_engine {
106
- @store_manager.take_snapshot @proxied_system
107
- }
108
- ensure
109
- Thread.current[:references] = nil
110
- end
111
- }
112
- end
113
-
114
- def execute_command(command)
115
- begin
116
- Thread.current[:references] = Hash.new
117
- super(command)
118
- ensure
119
- Thread.current[:references] = nil
120
- end
121
- end
122
-
123
- def register_proxy(proxy)
124
- @proxies[ proxy.proxy_id.to_s ] = proxy
125
- end
126
-
127
- def proxy_by_id( id, related_symbol = nil, parent_proxy_id = nil )
128
- p = @proxies[ id.to_s ]
129
- return p unless p.nil?
130
- if !related_symbol.nil? && !parent_proxy_id.nil?
131
- return create_nested_proxy( parent_proxy_id, related_symbol )
132
- end
133
- nil
134
- end
135
-
136
- def create_nested_proxy( parent_proxy_id, related_symbol )
137
- @proxies_lock.synchronize {
138
- parent_proxy = proxy_by_id( parent_proxy_id )
139
- target = parent_proxy.target
140
- nested_target = target.send( related_symbol )
141
- new_proxy = HPrevalence::Transparent::NestedTransparentProxy.new(
142
- nested_target, related_symbol, parent_proxy_id )
143
- target._set_proxy( related_symbol, new_proxy )
144
- return new_proxy
145
- }
146
- end
147
-
148
- def create_result_proxy( target )
149
- @proxies_lock.synchronize {
150
- # parent_proxy = proxy_by_id( parent_proxy_id )
151
- # target = parent_proxy.target
152
- # result = target.send( related_symbol, *args )
153
- new_proxy = HPrevalence::Transparent::TransparentProxy.new( target )
154
- return new_proxy
155
- }
156
- end
157
-
158
- def within_engine()
159
- begin
160
- Thread.current[:engine] = self
161
- yield
162
- ensure
163
- Thread.current[:engine] = nil
164
- end
165
- end
166
-
167
- def restore(proxy)
168
- proxy.engine_id = @engine_id
169
- p = proxy_by_id( proxy.proxy_id )
170
- if (p.nil?)
171
- register_proxy(proxy)
172
- p = proxy
173
- end
174
- p
175
- end
176
-
177
- def self.create_nested_proxy( parent_proxy_id, symbol, engine_id )
178
- within_engine( engine_id ) { |engine|
179
- engine.create_nested_proxy( parent_proxy_id, symbol )
180
- }
181
- end
182
-
183
- def self.create_result_proxy( target, engine_id )
184
- within_engine( engine_id ) { |engine|
185
- engine.create_result_proxy( target )
186
- }
187
- end
188
-
189
- def self.within_engine( engine_id )
190
- engine = @@engines[ engine_id ]
191
- raise 'Engine not found' if engine.nil?
192
- begin
193
- # puts 'engine>'
194
- Thread.current[:engine] = engine
195
- yield(engine)
196
- ensure
197
- Thread.current[:engine] = nil
198
- # puts 'engine<'
199
- end
200
- end
201
-
202
- def self.current()
203
- engine = Thread.current[:engine]
204
-
205
- if block_given?
206
- # puts 'engine.current'
207
- raise 'Engine not found' if engine.nil?
208
- yield( engine )
209
- # puts 'end.current'
210
- else
211
- return engine
212
- end
213
- end
214
-
215
74
  protected
216
75
 
217
- def self.register_engine( engine )
218
- @@class_lock.synchronize {
219
- @@engines[engine.engine_id] = engine
220
- }
221
- end
222
-
223
- def self.unregister_engine( engine )
224
- @@class_lock.synchronize {
225
- @@engines.delete(engine.engine_id)
226
- }
227
- end
228
-
229
- def add_engine_id_method( system )
230
- temp_id = @engine_id
231
- system.instance_eval {
232
- @engine_id = temp_id
233
- }
76
+ def set_time_if_requested(command)
77
+ if command.respond_to?( :now= )
78
+ command.now = Time.now()
79
+ end
234
80
  end
235
81
  end
236
82
 
@@ -253,6 +99,7 @@ module HPrevalence
253
99
  def initialize( engine, snapshot_interval )
254
100
  @engine = engine
255
101
  @snapshot_interval = snapshot_interval
102
+ start_snapshot_thread
256
103
  end
257
104
 
258
105
  def start_snapshot_thread
@@ -1,65 +1,47 @@
1
1
 
2
- class BinaryCommandSerializer
3
-
4
- def initialize( io )
2
+ class CommandSerializer
3
+ def initialize( io, marshaler )
5
4
  raise 'Invalid stream' if io.nil?
6
- @io = io
5
+ @io, @marshaler = io, marshaler
7
6
  @io.binmode
8
- # register_finalize()
9
7
  end
10
8
 
11
9
  def <<(command)
12
10
  raise 'Invalid command' if command.nil?
13
- Marshal.dump( command, @io )
11
+ @marshaler.serialize_to_stream( command, @io )
14
12
  @io.flush
15
13
  @io.fsync
16
14
  end
17
15
 
18
- def self.restore_from_io( io, system )
19
- # Theorically this should work and its more elegant than the current version
16
+ def self.restore_from_io( io, system, marshaler )
17
+ # Theorically this should work and its more elegant than the current version
20
18
  # Marshal.load( io ) { |command|
21
19
  # command.execute( system )
22
20
  # }
23
21
  while( !io.eof? )
24
- command = Marshal.load( io )
22
+ command = marshaler.restore( io )
25
23
  command.execute( system )
26
24
  end
27
25
  end
28
26
 
29
27
  def close
30
28
  @io.close
31
- # unregister_finalize
32
29
  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
30
  end
48
31
 
49
32
  class CommandLogger
50
-
51
33
  Logger_Extension = 'commandlog'
52
34
 
53
35
  attr_reader :current_file_name
54
36
 
55
- def initialize( iomanager )
56
- @iomanager = iomanager
37
+ def initialize( iomanager, marshaler )
38
+ @iomanager, @marshaler = iomanager, marshaler
57
39
  end
58
40
 
59
41
  def create_command_store()
60
42
  stream = @iomanager.create_new_stream( Logger_Extension )
61
43
  @current_file_name = stream.full_name
62
- BinaryCommandSerializer.new( stream )
44
+ CommandSerializer.new( stream, @marshaler )
63
45
  end
64
46
 
65
47
  def log_files
@@ -69,29 +51,24 @@ class CommandLogger
69
51
  # removes all command_logs as a snapshot has been taken
70
52
  def reset_commands()
71
53
  streams = @iomanager.obtain_ordered_read_streams( Logger_Extension )
72
-
73
54
  streams.each do |stream|
74
55
  stream.close
75
56
  File.delete stream.full_name
76
57
  end
77
-
78
58
  end
79
59
 
80
60
  def restore( system )
81
61
  streams = @iomanager.obtain_ordered_read_streams( Logger_Extension )
82
62
 
83
63
  begin
84
-
85
64
  streams.each do |stream|
86
- BinaryCommandSerializer.restore_from_io( stream, system )
65
+ CommandSerializer.restore_from_io( stream, system, @marshaler )
87
66
  end
88
-
89
67
  ensure
90
68
  streams.each do |stream|
91
69
  stream.close
92
70
  end
93
71
  end
94
-
95
72
  end
96
73
 
97
74
  end
@@ -0,0 +1,17 @@
1
+
2
+ class DefaultMarshaller
3
+
4
+ def serialize(graph)
5
+ Marshal.dump(graph)
6
+ end
7
+
8
+ def serialize_to_stream(graph, stream)
9
+ Marshal.dump(graph, stream)
10
+ end
11
+
12
+ def restore(stream)
13
+ Marshal.restore(stream)
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,26 @@
1
+
2
+ require 'soap/marshal'
3
+
4
+ #
5
+ # Probably the most inneficient
6
+ # marshaller implementation
7
+ #
8
+ class SoapMarshaller
9
+
10
+ def serialize(graph)
11
+ content = SOAP::Marshal.dump(graph)
12
+ Marshal.dump( content )
13
+ end
14
+
15
+ def serialize_to_stream(graph, stream)
16
+ content = SOAP::Marshal.dump(graph)
17
+ Marshal.dump( content, stream )
18
+ end
19
+
20
+ def restore(stream)
21
+ content = Marshal.load( stream )
22
+ SOAP::Marshal.load(content)
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,22 @@
1
+
2
+ require 'yaml'
3
+
4
+ class YamlMarshaller
5
+
6
+ def serialize(graph)
7
+ content = YAML.dump(graph)
8
+ Marshal.dump( content )
9
+ end
10
+
11
+ def serialize_to_stream(graph, stream)
12
+ content = YAML.dump(graph)
13
+ Marshal.dump( content, stream )
14
+ end
15
+
16
+ def restore(stream)
17
+ content = Marshal.load( stream )
18
+ YAML.load(content)
19
+ end
20
+
21
+ end
22
+
@@ -1,16 +1,15 @@
1
1
 
2
2
  class DefaultModelSerializer
3
-
4
3
  Snapshot_Extension = 'snapshot'
5
4
 
6
- def initialize( iomanager )
7
- @iomanager = iomanager
5
+ def initialize( iomanager, marshaller )
6
+ @iomanager, @marshaller = iomanager, marshaller
8
7
  end
9
8
 
10
9
  def dump( object_model )
11
10
  begin
12
11
  stream = @iomanager.create_new_stream( Snapshot_Extension )
13
- Marshal.dump( object_model, stream )
12
+ @marshaller.serialize_to_stream( object_model, stream )
14
13
  ensure
15
14
  stream.close
16
15
  end
@@ -22,7 +21,7 @@ class DefaultModelSerializer
22
21
  return nil if stream.nil?
23
22
 
24
23
  begin
25
- object_model = Marshal.load( stream )
24
+ object_model = @marshaller.restore( stream )
26
25
  ensure
27
26
  stream.close
28
27
  end
@@ -32,52 +31,39 @@ class DefaultModelSerializer
32
31
 
33
32
  end
34
33
 
35
- #class SmartModelSerializer
36
- #
37
- # Snapshot_Extension = 'ssnapshot'
34
+ #
35
+ # TODO: VersionIndependentSerializer is intended to handle
36
+ # small modifications in the object model, like new fields or
37
+ # even excluded fields, without breaking the existing snapshots
38
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
-
39
+ class VersionIndependentSerializer
40
+ Snapshot_Extension = 'version-ind-snapshot'
83
41
 
42
+ def initialize( iomanager, marshaller )
43
+ @iomanager, @marshaller = iomanager, marshaller
44
+ end
45
+
46
+ def dump( object_model )
47
+ begin
48
+ stream = @iomanager.create_new_stream( Snapshot_Extension )
49
+ @marshaller.serialize_to_stream( object_model, stream )
50
+ ensure
51
+ stream.close
52
+ end
53
+ end
54
+
55
+ def load()
56
+ object_model = nil
57
+ stream = @iomanager.obtain_latest_read_stream( Snapshot_Extension )
58
+ return nil if stream.nil?
59
+
60
+ begin
61
+ object_model = @marshaller.restore( stream )
62
+ ensure
63
+ stream.close
64
+ end
65
+
66
+ object_model
67
+ end
68
+
69
+ end