madeleine 0.8.0 → 0.9.0.pre

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0254e4a5cd6fe35768ce76fb92b0804724a83663
4
+ data.tar.gz: cc5860e5c27def4543d104edc0ce30f0f6acf65a
5
+ SHA512:
6
+ metadata.gz: e009aac28e96a06499feeff40c43156bc8dfa7139ae20588fc2c5eef88277868b77cbff63be153971b59230e956b35b91483783dd8983ce6e33a8837c301a343
7
+ data.tar.gz: c5c67ada967d93f9d280ade1304c07328b439acf4aa787e5c1441d68213394252c4bd8a1227a3f8485db46cfe98856969360b08e07fd896dcdc08ea87b4c65d2
@@ -1,3 +1,5 @@
1
+ * Ruby 2.0 fix for self-tests.
2
+
1
3
  Madeleine 0.8.0 (December 17, 2012):
2
4
 
3
5
  * Ruby 1.9 compatible (requires at least 1.8.7)
@@ -0,0 +1,84 @@
1
+ # Madeleine
2
+
3
+ Madeleine is a Ruby implementation of transparent persistence of business
4
+ objects, using command logging and complete system snapshots.
5
+
6
+ https://github.com/ghostganz/madeleine
7
+
8
+ ### Usage
9
+
10
+ ```ruby
11
+ require 'madeleine'
12
+
13
+ # Create an application as a prevalent system
14
+
15
+ madeleine = SnapshotMadeleine.new("my_example_storage") {
16
+ # Creating the initial empty system. This is how the application
17
+ # is bootstrapped on each startup (until the first snapshot is taken).
18
+ # All the persistent data needs to be reachable from this object.
19
+ # For this example, the application's whole dataset is a hash
20
+ # with a counter:
21
+ {:counter => 0}
22
+ }
23
+
24
+ # To operate on the system, we need commands. For this example,
25
+ # we can do additions to our counter:
26
+ class AdditionCommand
27
+ def initialize(number)
28
+ @number = number
29
+ end
30
+
31
+ def execute(system)
32
+ # This is the only place from where we're allowed to modify
33
+ # the system.
34
+ system[:counter] += @number
35
+ end
36
+ end
37
+
38
+ # Do modifications of the system by sending commands through
39
+ # the Madeleine instance:
40
+
41
+ command = AdditionCommand.new(12)
42
+ madeleine.execute_command(command)
43
+
44
+ # The commands are written to the command log before executed.
45
+ # The next time the application starts, all the commands in the
46
+ # log are re-applied to the system, returning it to the state it
47
+ # had when it was shut down.
48
+
49
+ # To avoid long start-up times when the command log gets large,
50
+ # you can do occasional snapshots of the entire system. You must
51
+ # also do a snapshot before deploying any changes in your application
52
+ # logic.
53
+
54
+ madeleine.take_snapshot
55
+ ```
56
+
57
+ ### Requirements
58
+
59
+ * Ruby 1.8.7 or later
60
+
61
+ ### Contact
62
+
63
+ Homepage: https://github.com/ghostganz/madeleine
64
+
65
+ ### License
66
+
67
+ BSD (see the file ```COPYING```)
68
+
69
+ ### Credits
70
+
71
+ Anders Bengtsson - Prevalence core impl.
72
+ Stephen Sykes - Automatic commands impl.
73
+
74
+ Madeleine's design is based on Prevayler, the original Java
75
+ prevalence layer.
76
+
77
+ With the help of patches, testing and feedback from:
78
+
79
+ Steve Conover, David Heinemeier Hansson, Johan Lind, Håkan Råberg,
80
+ IIMA Susumu, Martin Tampe and Jon Tirsén
81
+
82
+ Thanks to Klaus Wuestefeld and the Prevayler developers for the
83
+ model of this software; to Minero Aoki for the installer; to Matz and
84
+ the core developers for the Ruby language!
@@ -42,21 +42,32 @@ module Madeleine
42
42
  # See: DefaultSnapshotMadeleine
43
43
  #
44
44
  # * <tt>directory_name</tt> - Storage directory to use. Will be created if needed.
45
- # * <tt>snapshot_marshaller</tt> - Marshaller to use for system snapshots. (Optional)
45
+ # * <tt>options</tt> - Options hash:
46
+ # * <tt>:snapshot_marshaller</tt> - Marshaller to use for system snapshots (defaults to Marshal)
47
+ # * <tt>:execution_context</tt> - Optional context to be passed to commands' execute() method as a second parameter
46
48
  # * <tt>new_system_block</tt> - Block to create a new system (if no stored system was found).
47
- def self.new(directory_name, snapshot_marshaller=Marshal, &new_system_block)
49
+ def self.new(directory_name, options = {}, &new_system_block)
50
+ if options.kind_of? Hash
51
+ options = {
52
+ :snapshot_marshaller => Marshal,
53
+ :execution_context => nil
54
+ }.merge(options)
55
+ else
56
+ # Backwards compat.
57
+ options = {:snapshot_marshaller => options}
58
+ end
59
+
48
60
  log_factory = DefaultLogFactory.new
49
61
  logger = Logger.new(directory_name,
50
62
  log_factory)
51
63
  snapshotter = Snapshotter.new(directory_name,
52
- snapshot_marshaller)
53
- lock = DefaultLock.new
64
+ options[:snapshot_marshaller])
54
65
  recoverer = Recoverer.new(directory_name,
55
- snapshot_marshaller)
66
+ options[:snapshot_marshaller])
56
67
  system = recoverer.recover_snapshot(new_system_block)
57
- executer = Executer.new(system)
68
+ executer = Executer.new(system, options[:execution_context])
58
69
  recoverer.recover_logs(executer)
59
- DefaultSnapshotMadeleine.new(system, logger, snapshotter, lock, executer)
70
+ DefaultSnapshotMadeleine.new(system, logger, snapshotter, executer)
60
71
  end
61
72
  end
62
73
 
@@ -65,13 +76,13 @@ module Madeleine
65
76
  # The prevalent system
66
77
  attr_reader :system
67
78
 
68
- def initialize(system, logger, snapshotter, lock, executer)
79
+ def initialize(system, logger, snapshotter, executer)
69
80
  SanityCheck.instance.run_once
70
81
 
71
82
  @system = system
72
83
  @logger = logger
73
84
  @snapshotter = snapshotter
74
- @lock = lock
85
+ @lock = Sync.new
75
86
  @executer = executer
76
87
 
77
88
  @closed = false
@@ -103,7 +114,7 @@ module Madeleine
103
114
  #
104
115
  # * <tt>query</tt> - The query command to execute
105
116
  def execute_query(query)
106
- @lock.synchronize_shared do
117
+ @lock.synchronize(:SH) do
107
118
  @executer.execute(query)
108
119
  end
109
120
  end
@@ -168,31 +179,20 @@ module Madeleine
168
179
 
169
180
  FILE_COUNTER_SIZE = 21 #:nodoc:
170
181
 
171
- class DefaultLock #:nodoc:
172
-
173
- def initialize
174
- @lock = Sync.new
175
- end
176
-
177
- def synchronize(&block)
178
- @lock.synchronize(&block)
179
- end
180
-
181
- def synchronize_shared(&block)
182
- @lock.synchronize(:SH, &block)
183
- end
184
- end
185
-
186
182
  class Executer #:nodoc:
187
-
188
- def initialize(system)
183
+ def initialize(system, context = nil)
189
184
  @system = system
185
+ @context = context
190
186
  @in_recovery = false
191
187
  end
192
188
 
193
189
  def execute(command)
194
190
  begin
195
- command.execute(@system)
191
+ if @context
192
+ command.execute(@system, @context)
193
+ else
194
+ command.execute(@system)
195
+ end
196
196
  rescue
197
197
  raise unless @in_recovery
198
198
  end
@@ -231,7 +231,7 @@ module Madeleine
231
231
  def recover_logs(executer)
232
232
  executer.recovery do
233
233
  CommandLog.log_file_names(@directory_name, FileService.new).each do |file_name|
234
- open(@directory_name + File::SEPARATOR + file_name, "rb") do |log|
234
+ open("#{@directory_name}#{File::SEPARATOR}#{file_name}", "rb") do |log|
235
235
  recover_log(executer, log)
236
236
  end
237
237
  end
@@ -255,11 +255,13 @@ module Madeleine
255
255
  end
256
256
 
257
257
  def name
258
- result = @path
259
- result += File::SEPARATOR
260
- result += sprintf("%0#{FILE_COUNTER_SIZE}d", @id)
261
- result += '.'
262
- result += @name
258
+ [
259
+ @path,
260
+ File::SEPARATOR,
261
+ sprintf("%0#{FILE_COUNTER_SIZE}d", @id),
262
+ '.',
263
+ @name
264
+ ].join
263
265
  end
264
266
  end
265
267
 
@@ -363,7 +365,7 @@ module Madeleine
363
365
  private
364
366
 
365
367
  def delete_log_files
366
- names = Dir.glob(@directory_name + File::SEPARATOR + "*.command_log")
368
+ names = Dir.glob("#{@directory_name}#{File::SEPARATOR}*.command_log")
367
369
  names.each do |name|
368
370
  name.untaint
369
371
  File.delete(name)
@@ -1,3 +1,4 @@
1
+ #encoding:utf-8
1
2
  #
2
3
  # Author:: Anders Bengtsson <ndrsbngtssn@yahoo.se>
3
4
  # Copyright:: Copyright (c) 2004-2006
@@ -11,7 +12,11 @@ module Madeleine
11
12
  include Singleton
12
13
 
13
14
  def initialize
14
- @testdata = "\x85\x00\x0a\0x0d\x0a".freeze
15
+ @testdata = "\x85\x00\x0a\0x0d\x0a"
16
+ if @testdata.respond_to?(:force_encoding)
17
+ @testdata.force_encoding('ASCII-8BIT')
18
+ end
19
+ @testdata.freeze
15
20
  @was_run = false
16
21
  end
17
22
 
@@ -1,3 +1,3 @@
1
1
  module Madeleine
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0.pre"
3
3
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madeleine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
5
- prerelease:
4
+ version: 0.9.0.pre
6
5
  platform: ruby
7
6
  authors:
8
- - Anders Bengtsson
7
+ - Anders Kindberg (Bengtsson)
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-12-17 00:00:00.000000000 Z
11
+ date: 2013-08-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: minitest
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,33 +27,29 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rdoc
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: Transparent persistence of system state using logging and snapshots
@@ -81,11 +74,12 @@ files:
81
74
  - contrib/test_batched.rb
82
75
  - contrib/test_scalability.rb
83
76
  - contrib/threaded_benchmark.rb
84
- - README
77
+ - README.md
85
78
  - CHANGES.txt
86
79
  - COPYING
87
80
  homepage: http://github.com/ghostganz/madeleine
88
81
  licenses: []
82
+ metadata: {}
89
83
  post_install_message:
90
84
  rdoc_options:
91
85
  - --exclude
@@ -97,21 +91,19 @@ rdoc_options:
97
91
  require_paths:
98
92
  - lib
99
93
  required_ruby_version: !ruby/object:Gem::Requirement
100
- none: false
101
94
  requirements:
102
- - - ! '>='
95
+ - - '>='
103
96
  - !ruby/object:Gem::Version
104
97
  version: 1.8.7
105
98
  required_rubygems_version: !ruby/object:Gem::Requirement
106
- none: false
107
99
  requirements:
108
- - - ! '>='
100
+ - - '>'
109
101
  - !ruby/object:Gem::Version
110
- version: '0'
102
+ version: 1.3.1
111
103
  requirements: []
112
104
  rubyforge_project:
113
- rubygems_version: 1.8.24
105
+ rubygems_version: 2.0.5
114
106
  signing_key:
115
- specification_version: 3
107
+ specification_version: 4
116
108
  summary: Madeleine is a Ruby implementation of Object Prevalence
117
109
  test_files: []
data/README DELETED
@@ -1,55 +0,0 @@
1
-
2
- Madeleine is a Ruby implementation of Object Prevalence: Transparent
3
- persistence of business objects using command logging and complete
4
- system snapshots.
5
-
6
- https://github.com/ghostganz/madeleine
7
-
8
- Madeleine's design is based on Prevayler, the original Java
9
- prevalence layer.
10
-
11
-
12
- Usage:
13
-
14
- require 'madeleine'
15
-
16
- # Create an application as a prevalent system
17
-
18
- madeleine = SnapshotMadeleine.new("my_example_storage") {
19
- SomeExampleApplication.new()
20
- }
21
-
22
- # Do modifications of the system by sending commands through
23
- # the Madeleine instance. A command is an object with a suitable
24
- # "execute(system)" method.
25
-
26
- madeleine.execute_command(command)
27
-
28
-
29
- Requirements:
30
-
31
- * Ruby 1.8.7 or later
32
-
33
- Contact:
34
-
35
- Homepage:
36
- https://github.com/ghostganz/madeleine
37
-
38
- License:
39
-
40
- BSD (see the file COPYING)
41
-
42
- Credits:
43
-
44
- Anders Bengtsson - Prevalence core impl.
45
- Stephen Sykes - Automatic commands impl.
46
-
47
- With the help of patches, testing and feedback from:
48
-
49
- Steve Conover, David Heinemeier Hansson, Johan Lind, Håkan Råberg,
50
- IIMA Susumu, Martin Tampe and Jon Tirsén
51
-
52
- Thanks to Klaus Wuestefeld and the Prevayler developers for the
53
- model of this software; to Minero Aoki for the installer; to Matz and
54
- the core developers for the Ruby language!
55
-