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.
- data/History.txt +67 -0
- data/Install.txt +21 -0
- data/Licence.txt +25 -0
- data/Manifest.txt +16 -0
- data/Rakefile +107 -99
- data/{Readme → Readme.txt} +61 -50
- data/lib/transaction/simple.rb +390 -597
- data/lib/transaction/simple/group.rb +13 -0
- data/lib/transaction/simple/threadsafe.rb +18 -2
- data/lib/transaction/simple/threadsafe/group.rb +13 -0
- data/setup.rb +1585 -0
- data/test/test_all.rb +25 -0
- data/test/test_broken_graph.rb +70 -0
- data/test/test_transaction_simple.rb +311 -0
- data/test/test_transaction_simple_group.rb +61 -0
- data/test/test_transaction_simple_threadsafe.rb +152 -0
- metadata +50 -44
- data/Changelog +0 -31
- data/Install +0 -6
- data/tests/tc_transaction_simple.rb +0 -277
- data/tests/tc_transaction_simple_group.rb +0 -44
- data/tests/tc_transaction_simple_threadsafe.rb +0 -135
- data/tests/testall.rb +0 -20
data/History.txt
ADDED
@@ -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 $
|
data/Install.txt
ADDED
@@ -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 $
|
data/Licence.txt
ADDED
@@ -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 $
|
data/Manifest.txt
ADDED
@@ -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
|
-
|
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 '
|
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
|
-
|
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
|
-
|
49
|
-
end
|
21
|
+
require 'transaction/simple'
|
50
22
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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 => [
|
63
|
-
file
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
114
|
-
|
119
|
+
File.open("Manifest.txt", "w") do |f|
|
120
|
+
f.puts paths.sort.join("\n")
|
121
|
+
end
|
122
|
+
end
|
data/{Readme → Readme.txt}
RENAMED
@@ -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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
The transactions supported by Transaction::Simple are not
|
8
|
-
|
9
|
-
|
10
|
-
object
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Copyright
|
31
|
-
Version
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
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
|
-
|
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
|
174
|
-
|
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.
|
179
|
-
|
180
|
-
|
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
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
Transaction::Simple::ThreadSafe. With transaction groups, some
|
191
|
-
of atomicity is assured.
|
192
|
-
* does not maintain Object#__id__ values on rewind or abort. This
|
193
|
-
|
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 $
|