transaction-simple 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ == Transaction::Simple 1.4.0 / 2007.02.03
2
+
3
+ * Adding a post-rewind hook (#_post_transaction_rewind) so that complex
4
+ graph objects can correct themselves after rewinding. See the
5
+ documentation for #rewind_transaction and tests/tc_broken_graph.rb for
6
+ more information.
7
+ * Removed all warnings.
8
+ * Deprecated the #transaction method.
9
+ * Various administrative changes:
10
+ - Converted to a hoe-driven project.
11
+ - Made the gem and .tar.gz files idempotent.
12
+ - Cleaned up the code a little further.
13
+ - Changed non-gem installer to setup.rb version 3.4.1.
14
+
15
+ == Transaction::Simple 1.3.1
16
+
17
+ * Explicitly clearing the transaction checkpoint on objects when the
18
+ last open transaction is committed or aborted.
19
+ * Fixed up behaviour to remove a lot of #respond_to? calls.
20
+
21
+ == Transaction::Simple 1.3.0
22
+
23
+ * Updated to fix a lot of warnings.
24
+ * Added a per-transaction-object list of excluded instance variables.
25
+ * Moved Transaction::simple::ThreadSafe to transaction/simple/threadsafe.
26
+ * Added transaction groups. Transaction groups are wrapper objects to
27
+ allow the coordination of transactions with a group of objects. There
28
+ are both normal and threadsafe versions of transaction groups.
29
+ * Fixed a long-standing problem where instance variables that were added
30
+ to an object after a transaction was started would remain.
31
+ * Reorganised unit tests.
32
+
33
+ == Transaction::Simple 1.2.0
34
+
35
+ * Added a RubyGem.
36
+ * Added a block form of Transaction::Simple.
37
+
38
+ == Transaction::Simple 1.1.1
39
+
40
+ * Cleaned up some documentation.
41
+
42
+ == Transaction::Simple 1.1
43
+
44
+ * Added Transaction::Simple::ThreadSafe for truly atomic and thread-safe
45
+ transactions.
46
+ * Fixed the description of Transaction::Simple to note that it is *not*
47
+ atomic because it is not implicitly thread-safe.
48
+ * Added support for named transactions. Named transactions can be used to
49
+ make checkpoints that can be committed, aborted, or rewound without
50
+ explicitly committing, aborting, or rewinding the intervening
51
+ transactions.
52
+
53
+ == Transaction::Simple 1.0
54
+
55
+ * Created. Initial release.
56
+
57
+ == Copyright
58
+ Transaction::Simple
59
+ Simple object transaction support for Ruby
60
+ http://rubyforge.org/projects/trans-simple/
61
+
62
+ Licensed under a MIT-style licence. See Licence.txt in the main
63
+ distribution for full licensing information.
64
+
65
+ Copyright (c) 2003 - 2007 Austin Ziegler
66
+
67
+ $Id: History.txt 50 2007-02-03 20:26:19Z austin $
@@ -0,0 +1,21 @@
1
+ == Installing Transaction::Simple
2
+
3
+ Transaction::Simple requires Ruby version 1.8.2 or better. It may be
4
+ installed with:
5
+
6
+ % ruby setup.rb
7
+
8
+ Alternatively, the RubyGems version of Transaction::Simple may be
9
+ installed from the usual sources.
10
+
11
+ == Copyright
12
+ Transaction::Simple
13
+ Simple object transaction support for Ruby
14
+ http://rubyforge.org/projects/trans-simple/
15
+
16
+ Licensed under a MIT-style licence. See Licence.txt in the main
17
+ distribution for full licensing information.
18
+
19
+ Copyright (c) 2003 - 2007 Austin Ziegler
20
+
21
+ $Id: Install.txt 47 2007-02-03 15:02:51Z austin $
@@ -0,0 +1,25 @@
1
+ Transaction::Simple
2
+ Simple object transaction support for Ruby
3
+ http://rubyforge.org/projects/trans-simple/
4
+
5
+ Copyright (c) 2003 - 2007 Austin Ziegler
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a
8
+ copy of this software and associated documentation files (the "Software"),
9
+ to deal in the Software without restriction, including without limitation
10
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ and/or sell copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
24
+
25
+ $Id: simple.rb,v 1.7 2005/06/12 19:48:17 austin Exp $
@@ -0,0 +1,16 @@
1
+ History.txt
2
+ Install.txt
3
+ Licence.txt
4
+ Manifest.txt
5
+ Rakefile
6
+ Readme.txt
7
+ lib/transaction/simple.rb
8
+ lib/transaction/simple/group.rb
9
+ lib/transaction/simple/threadsafe.rb
10
+ lib/transaction/simple/threadsafe/group.rb
11
+ setup.rb
12
+ test/test_all.rb
13
+ test/test_broken_graph.rb
14
+ test/test_transaction_simple.rb
15
+ test/test_transaction_simple_group.rb
16
+ test/test_transaction_simple_threadsafe.rb
data/Rakefile CHANGED
@@ -1,114 +1,122 @@
1
1
  #! /usr/bin/env rake
2
- $LOAD_PATH.unshift('lib')
2
+ #--
3
+ # Transaction::Simple
4
+ # Simple object transaction support for Ruby
5
+ # http://rubyforge.org/projects/trans-simple/
6
+ # Version 1.4.0
7
+ #
8
+ # Licensed under a MIT-style licence. See Licence.txt in the main
9
+ # distribution for full licensing information.
10
+ #
11
+ # Copyright (c) 2003 - 2007 Austin Ziegler
12
+ #
13
+ # $Id: Rakefile 51 2007-02-03 21:45:27Z austin $
14
+ #++
3
15
 
4
16
  require 'rubygems'
5
- require 'rake/gempackagetask'
6
- require 'rake/contrib/rubyforgepublisher'
7
- require 'transaction/simple'
8
- require 'archive/tar/minitar'
9
- require 'zlib'
10
-
11
- DISTDIR = "transaction-simple-#{Transaction::Simple::TRANSACTION_SIMPLE_VERSION}"
12
- TARDIST = "../#{DISTDIR}.tar.gz"
13
-
14
- DATE_RE = %r<(\d{4})[./-]?(\d{2})[./-]?(\d{2})(?:[\sT]?(\d{2})[:.]?(\d{2})[:.]?(\d{2})?)?>
15
-
16
- if ENV['RELEASE_DATE']
17
- year, month, day, hour, minute, second = DATE_RE.match(ENV['RELEASE_DATE']).captures
18
- year ||= 0
19
- month ||= 0
20
- day ||= 0
21
- hour ||= 0
22
- minute ||= 0
23
- second ||= 0
24
- ReleaseDate = Time.mktime(year, month, day, hour, minute, second)
25
- else
26
- ReleaseDate = nil
27
- end
28
-
29
- task :test do |t|
30
- require 'test/unit/testsuite'
31
- require 'test/unit/ui/console/testrunner'
32
-
33
- runner = Test::Unit::UI::Console::TestRunner
17
+ require 'hoe'
34
18
 
35
- $LOAD_PATH.unshift('tests')
36
- $stderr.puts "Checking for test cases:" if t.verbose
37
- Dir['tests/**/tc_*.rb'].each do |testcase|
38
- $stderr.puts "\t#{testcase}" if t.verbose
39
- load testcase
40
- end
41
-
42
- suite = Test::Unit::TestSuite.new("Transaction::Simple")
43
-
44
- ObjectSpace.each_object(Class) do |testcase|
45
- suite << testcase.suite if testcase < Test::Unit::TestCase
46
- end
19
+ $LOAD_PATH.unshift('lib')
47
20
 
48
- runner.run(suite)
49
- end
21
+ require 'transaction/simple'
50
22
 
51
- spec = eval(File.read("transaction-simple.gemspec"))
52
- spec.version = Transaction::Simple::TRANSACTION_SIMPLE_VERSION
53
- desc "Build the RubyGem for Transaction::Simple"
54
- task :gem => [ :test ]
55
- Rake::GemPackageTask.new(spec) do |g|
56
- g.need_tar = false
57
- g.need_zip = false
58
- g.package_dir = ".."
23
+ TSVER = Transaction::Simple::TRANSACTION_SIMPLE_VERSION
24
+ DISTDIR = "transaction-simple-#{TSVER}"
25
+ TARFILE = "pkg/#{DISTDIR}.tar.gz"
26
+ MANIFEST = File.read("Manifest.txt").split
27
+
28
+ Hoe.new "transaction-simple", TSVER do |p|
29
+ p.rubyforge_name = "trans-simple"
30
+ # This is a lie becasue I will continue to use Archive::Tar::Minitar.
31
+ p.need_tar = false
32
+ # need_zip - Should package create a zipfile? [default: false]
33
+
34
+ p.author = "Austin Ziegler"
35
+ p.email = "austin@rubyforge.org"
36
+ p.url = "http://rubyforge.org/projects/trans-simple"
37
+ p.summary = "Simple object transaction support for Ruby."
38
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
39
+ p.description = p.paragraphs_of("Readme.txt", 1..1).join("\n\n")
40
+
41
+ p.spec_extras[:required_ruby_version] = ">=1.8.2"
42
+ p.spec_extras[:extra_rdoc_files] = MANIFEST.grep(/txt$/) -
43
+ ["Manifest.txt"]
44
+ p.clean_globs << "./**/log"
45
+
46
+ # extra_deps - An array of rubygem dependencies.
47
+ # clean_globs - An array of file patterns to delete on clean.
48
+ # rdoc_pattern - A regexp to match documentation files against the manifest.
49
+ # spec_extras - A hash of extra values to set in the gemspec.
50
+ # test_globs - An array of test file patterns [default: test/**/test_*.rb]
51
+
52
+ # bin_files
53
+ # lib_files
54
+ # spec
55
+ # test_files
59
56
  end
60
57
 
61
58
  desc "Build a Transaction::Simple .tar.gz distribution."
62
- task :tar => [ TARDIST ]
63
- file TARDIST => [ :test ] do |t|
64
- current = File.basename(Dir.pwd)
65
- Dir.chdir("..") do
66
- begin
67
- files = Dir["#{current}/**/*"].select { |dd| dd !~ %r{(?:/CVS/?|~$)} }
68
- files.map! do |dd|
69
- ddnew = dd.gsub(/^#{current}/, DISTDIR)
70
- mtime = ReleaseDate || File.stat(dd).mtime
71
- if File.directory?(dd)
72
- { :name => ddnew, :mode => 0755, :dir => true, :mtime => mtime }
73
- else
74
- if dd =~ %r{bin/}
75
- mode = 0755
76
- else
77
- mode = 0644
78
- end
79
- data = File.read(dd)
80
- { :name => ddnew, :mode => mode, :data => data, :size => data.size,
81
- :mtime => mtime }
82
- end
83
- end
84
-
85
- ff = File.open(t.name.gsub(%r{^\.\./}o, ''), "wb")
86
- gz = Zlib::GzipWriter.new(ff)
87
- tw = Archive::Tar::Minitar::Writer.new(gz)
59
+ task :tar => [ TARFILE ]
60
+ file TARFILE => [ :test ] do |t|
61
+ require 'archive/tar/minitar'
62
+ require 'zlib'
63
+ files = MANIFEST.map { |f|
64
+ fn = File.join(DISTDIR, f)
65
+ tm = File.stat(f).mtime
66
+
67
+ if File.directory?(f)
68
+ { :name => fn, :mode => 0755, :dir => true, :mtime => tm }
69
+ else
70
+ mode = if f =~ %r{^bin}
71
+ 0755
72
+ else
73
+ 0644
74
+ end
75
+ data = File.read(f)
76
+ { :name => fn, :mode => mode, :data => data, :size => data.size,
77
+ :mtime => tm }
78
+ end
79
+ }
88
80
 
89
- files.each do |entry|
90
- if entry[:dir]
91
- tw.mkdir(entry[:name], entry)
92
- else
93
- tw.add_file_simple(entry[:name], entry) { |os| os.write(entry[:data]) }
94
- end
81
+ begin
82
+ unless File.directory?(File.dirname(t.name))
83
+ require 'fileutils'
84
+ File.mkdir_p File.dirname(t.name)
85
+ end
86
+ tf = File.open(t.name, 'wb')
87
+ gz = Zlib::GzipWriter.new(tf)
88
+ tw = Archive::Tar::Minitar::Writer.new(gz)
89
+
90
+ files.each do |entry|
91
+ if entry[:dir]
92
+ tw.mkdir(entry[:name], entry)
93
+ else
94
+ tw.add_file_simple(entry[:name], entry) { |os|
95
+ os.write(entry[:data])
96
+ }
95
97
  end
96
- ensure
97
- tw.close if tw
98
- gz.close if gz
99
98
  end
99
+ ensure
100
+ tw.close if tw
101
+ gz.close if gz
100
102
  end
101
103
  end
102
- task TARDIST => [ :test ]
103
-
104
- desc "Build the rdoc documentation for Transaction::Simple"
105
- task :docs do
106
- require 'rdoc/rdoc'
107
- rdoc_options = %w(--title Transaction::Simple --main Readme --line-numbers)
108
- files = FileList[*%w(Readme Changelog bin/**/*.rb lib/**/*.rb)]
109
- rdoc_options += files.to_a
110
- RDoc::RDoc.new.document(rdoc_options)
111
- end
104
+ task :package => [ TARFILE ]
105
+
106
+ task :build_manifest do |t|
107
+ require 'find'
108
+
109
+ paths = []
110
+ Find.find(".") do |path|
111
+ next if File.directory?(path)
112
+ next if path =~ /\.svn/
113
+ next if path =~ %r{/research/}
114
+ next if path =~ /\.swp$/
115
+ next if path =~ /~$/
116
+ paths << path.sub(%r{^\./}, '')
117
+ end
112
118
 
113
- desc "Build everything."
114
- task :default => [ :tar, :gem ]
119
+ File.open("Manifest.txt", "w") do |f|
120
+ f.puts paths.sort.join("\n")
121
+ end
122
+ end
@@ -1,38 +1,40 @@
1
1
  = Transaction::Simple for Ruby
2
+
2
3
  Transaction::Simple provides a generic way to add active transaction
3
- support to objects. The transaction methods added by this module will
4
- work with most objects, excluding those that cannot be Marshal-ed
5
- (bindings, procedure objects, IO instances, or singleton objects).
6
-
7
- The transactions supported by Transaction::Simple are not backend
8
- transaction; that is, they are not associated with any sort of data
9
- store. They are "live" transactions occurring in memory and in the
10
- object itself. This is to allow "test" changes to be made to an object
11
- before making the changes permanent.
12
-
13
- Transaction::Simple can handle an "infinite" number of transaction
14
- levels (limited only by memory). If I open two transactions, commit the
15
- second, but abort the first, the object will revert to the original
16
- version.
17
-
18
- Transaction::Simple supports "named" transactions, so that multiple
19
- levels of transactions can be committed, aborted, or rewound by
20
- referring to the appropriate name of the transaction. Names may be any
21
- object except nil.
22
-
23
- Version 1.3.0 of Transaction::Simple adds transaction groups. A
24
- transaction group is an object wrapper that manages a group of objects
25
- as if they were a single object for the purpose of transaction
26
- management. All transactions for this group of objects should be
27
- performed against the transaction group object, not against individual
28
- objects in the group.
29
-
30
- Copyright: Copyright 2003 - 2005 by Austin Ziegler
31
- Version: 1.3.0
32
- Licence: MIT-Style
33
-
34
- Thanks to David Black and Mauricio Fern�ndez for their help with this
35
- library.
4
+ support to objects. The transaction methods added by this module will work
5
+ with most objects, excluding those that cannot be Marshal-ed (bindings,
6
+ procedure objects, IO instances, or singleton objects).
7
+
8
+ The transactions supported by Transaction::Simple are not associated with
9
+ any sort of data store. They are "live" transactions occurring in memory
10
+ on the object itself. This is to allow "test" changes to be made to an
11
+ object before making the changes permanent.
12
+
13
+ Transaction::Simple can handle an "infinite" number of transaction levels
14
+ (limited only by memory). If I open two transactions, commit the second,
15
+ but abort the first, the object will revert to the original version.
16
+
17
+ Transaction::Simple supports "named" transactions, so that multiple levels
18
+ of transactions can be committed, aborted, or rewound by referring to the
19
+ appropriate name of the transaction. Names may be any object except nil.
20
+
21
+ Transaction groups are also supported. A transaction group is an object
22
+ wrapper that manages a group of objects as if they were a single object
23
+ for the purpose of transaction management. All transactions for this group
24
+ of objects should be performed against the transaction group object, not
25
+ against individual objects in the group.
26
+
27
+ Version 1.4.0 of Transaction::Simple adds a new post-rewind hook so that
28
+ complex graph objects of the type in tests/tc_broken_graph.rb can correct
29
+ themselves.
30
+
31
+ Copyright:: Copyright (c) 2003 - 2007 by Austin Ziegler
32
+ Version:: 1.4.0
33
+ Homepage:: http://rubyforge.org/projects/trans-simple/
34
+ Licence:: MIT-Style; see Licence.txt
35
+
36
+ Thanks to David Black, Mauricio Fernandez, Patrick Hurley, Pit Capitain, and
37
+ Matz for their assistance with this library.
36
38
 
37
39
  == Usage
38
40
  include 'transaction/simple'
@@ -163,31 +165,40 @@ library.
163
165
  y = -> "And you, too."
164
166
 
165
167
  == Thread Safety
166
- Threadsafe version of Transaction::Simple and Transaction::Simple::Group
168
+ Threadsafe versions of Transaction::Simple and Transaction::Simple::Group
167
169
  exist; these are loaded from 'transaction/simple/threadsafe' and
168
- 'transaction/simple/threadsafe/group', respectively, and are represented
169
- in Ruby code as Transaction::Simple::ThreadSafe and
170
+ 'transaction/simple/threadsafe/group', respectively, and are represented in
171
+ Ruby code as Transaction::Simple::ThreadSafe and
170
172
  Transaction::Simple::ThreadSafe::Group, respectively.
171
173
 
172
174
  == Contraindications
173
- While Transaction::Simple is very useful, it has some severe limitations
174
- that must be understood. Transaction::Simple:
175
+ While Transaction::Simple is very useful, it has limitations that must be
176
+ understood prior to using it. Transaction::Simple:
175
177
 
176
178
  * uses Marshal. Thus, any object which cannot be Marshal-ed cannot use
177
179
  Transaction::Simple. In my experience, this affects singleton objects
178
- more often than any other object. It may be that Ruby 2.0 will solve
179
- this problem.
180
- * does not manage resources. Resources external to the object and its
181
- instance variables are not managed at all. However, all instance
180
+ more often than any other object.
181
+ * does not manage external resources. Resources external to the object and
182
+ its instance variables are not managed at all. However, all instance
182
183
  variables and objects "belonging" to those instance variables are
183
184
  managed. If there are object reference counts to be handled,
184
185
  Transaction::Simple will probably cause problems.
185
186
  * is not thread-safe. In the ACID ("atomic, consistent, isolated,
186
- durable") test, Transaction::Simple provides C and D, but it is up to
187
- the user of Transaction::Simple to provide isolation. Transactions
188
- should be considered "critical sections" in multi-threaded
189
- applications. Thread safety can be ensured with
190
- Transaction::Simple::ThreadSafe. With transaction groups, some level
191
- of atomicity is assured.
192
- * does not maintain Object#__id__ values on rewind or abort. This may
193
- change for future versions.
187
+ durable") test, Transaction::Simple provides consistency and durability, but
188
+ cannot itself provide isolation. Transactions should be considered "critical
189
+ sections" in multi-threaded applications. Thread safety of the transaction
190
+ acquisition and release process itself can be ensured with the thread-safe
191
+ version, Transaction::Simple::ThreadSafe. With transaction groups, some
192
+ level of atomicity is assured.
193
+ * does not maintain Object#__id__ values on rewind or abort. This only affects
194
+ complex self-referential graphs. tests/tc_broken_graph.rb demonstrates this
195
+ and its mitigation with the new post-rewind hook. #_post_transaction_rewind.
196
+ Matz has implemented an experimental feature in Ruby 1.9 that may find its
197
+ way into the released Ruby 1.9.1 and ultimately Ruby 2.0 that would obviate
198
+ the need for #_post_transaction_rewind. Pit Capitain has also suggested a
199
+ workaround that does not require changes to core Ruby, but does not work in
200
+ all cases. A final resolution is still pending further discussion.
201
+ * Can be a memory hog if you use many levels of transactions on many
202
+ objects.
203
+
204
+ $Id: Readme.txt 50 2007-02-03 20:26:19Z austin $