spinoza 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +66 -3
- data/lib/spinoza/calvin/executor.rb +107 -0
- data/lib/spinoza/calvin/node.rb +44 -0
- data/lib/spinoza/calvin/readcaster.rb +50 -0
- data/lib/spinoza/calvin/scheduler.rb +134 -0
- data/lib/spinoza/calvin/sequencer.rb +74 -0
- data/lib/spinoza/common.rb +3 -0
- data/lib/spinoza/system/link.rb +33 -0
- data/lib/spinoza/system/lock-manager.rb +22 -8
- data/lib/spinoza/system/log.rb +95 -0
- data/lib/spinoza/system/meta-log.rb +103 -0
- data/lib/spinoza/system/model.rb +14 -0
- data/lib/spinoza/system/node.rb +56 -7
- data/lib/spinoza/system/operation.rb +22 -6
- data/lib/spinoza/system/store.rb +15 -14
- data/lib/spinoza/system/{table-spec.rb → table.rb} +10 -6
- data/lib/spinoza/system/timeline.rb +81 -0
- data/lib/spinoza/transaction.rb +170 -39
- data/lib/spinoza/version.rb +1 -1
- data/test/test-executor.rb +110 -0
- data/test/test-link.rb +43 -0
- data/test/test-log.rb +47 -0
- data/test/test-meta-log.rb +63 -0
- data/test/test-node.rb +35 -14
- data/test/test-readcaster.rb +87 -0
- data/test/test-scheduler.rb +163 -0
- data/test/test-sequencer.rb +78 -0
- data/test/test-timeline.rb +58 -0
- data/test/test-transaction.rb +75 -18
- metadata +42 -3
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'spinoza/system/log'
|
3
|
+
require 'spinoza/system/meta-log'
|
4
|
+
require 'spinoza/calvin/node'
|
5
|
+
|
6
|
+
class TestSequencer < Minitest::Test
|
7
|
+
include Spinoza
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@timeline = Timeline.new
|
11
|
+
@log = Log.new dt_durable: 0.300, dt_replicated: 0.500
|
12
|
+
@meta_log = MetaLog.new dt_quorum: 0.300, dt_replicated: 0.500
|
13
|
+
|
14
|
+
@node = Calvin::Node[
|
15
|
+
timeline: @timeline,
|
16
|
+
log: @log,
|
17
|
+
meta_log: @meta_log,
|
18
|
+
sequencer: :none,
|
19
|
+
scheduler: :none
|
20
|
+
]
|
21
|
+
|
22
|
+
@other_node = Calvin::Node[
|
23
|
+
timeline: @timeline,
|
24
|
+
log: @log,
|
25
|
+
meta_log: @meta_log,
|
26
|
+
sequencer: :none,
|
27
|
+
scheduler: :none
|
28
|
+
]
|
29
|
+
|
30
|
+
@dt = 0.010
|
31
|
+
@sequencer = Calvin::Sequencer.new node: @node, dt_epoch: @dt
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_sequencer
|
35
|
+
sid = @sequencer.id
|
36
|
+
@sequencer.accept_transaction "t1"
|
37
|
+
@sequencer.accept_transaction "t2"
|
38
|
+
@timeline.evolve @dt
|
39
|
+
|
40
|
+
batch_ids = (0..2).map {|i| @meta_log.get(i, node: @other_node)}
|
41
|
+
assert_equal nil, batch_ids[0]
|
42
|
+
assert_equal nil, batch_ids[1]
|
43
|
+
assert_equal nil, batch_ids[2]
|
44
|
+
|
45
|
+
@sequencer.accept_transaction "t3"
|
46
|
+
@sequencer.accept_transaction "t4"
|
47
|
+
@timeline.evolve @dt
|
48
|
+
|
49
|
+
batch_ids = (0..2).map {|i| @meta_log.get(i, node: @other_node)}
|
50
|
+
assert_equal nil, batch_ids[0]
|
51
|
+
assert_equal nil, batch_ids[1]
|
52
|
+
assert_equal nil, batch_ids[2]
|
53
|
+
|
54
|
+
@timeline.evolve @log.dt_durable + @meta_log.dt_replicated - @dt
|
55
|
+
|
56
|
+
batch_ids = (0..2).map {|i| @meta_log.get(i, node: @other_node)}
|
57
|
+
assert_equal [sid, 1], batch_ids[0]
|
58
|
+
assert_equal nil, batch_ids[1]
|
59
|
+
assert_equal nil, batch_ids[2]
|
60
|
+
|
61
|
+
@timeline.evolve @dt
|
62
|
+
|
63
|
+
batch_ids = (0..2).map {|i| @meta_log.get(i, node: @other_node)}
|
64
|
+
assert_equal [sid, 1], batch_ids[0]
|
65
|
+
assert_equal [sid, 2], batch_ids[1]
|
66
|
+
assert_equal nil, batch_ids[2]
|
67
|
+
|
68
|
+
@timeline.evolve 2.000
|
69
|
+
|
70
|
+
batch_ids = (0..2).map {|i| @meta_log.get(i, node: @other_node)}
|
71
|
+
assert_equal [sid, 1], batch_ids[0]
|
72
|
+
assert_equal [sid, 2], batch_ids[1]
|
73
|
+
assert_equal nil, batch_ids[2]
|
74
|
+
|
75
|
+
assert_equal ["t1", "t2"], @log.read([sid, 1], node: @node)
|
76
|
+
assert_equal ["t3", "t4"], @log.read([sid, 2], node: @node)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'spinoza/system/timeline'
|
3
|
+
|
4
|
+
class TestTimeline < Minitest::Test
|
5
|
+
include Spinoza
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@tl = Timeline.new
|
9
|
+
|
10
|
+
@node = {}
|
11
|
+
def @node.foo(**h); update h; end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_timeline_empty
|
15
|
+
assert_equal 0, @tl.now
|
16
|
+
|
17
|
+
assert_nil @tl.step
|
18
|
+
assert_equal 0, @tl.now
|
19
|
+
|
20
|
+
assert_equal 1.0, @tl.evolve(1.0)
|
21
|
+
assert_equal 1.0, @tl.now
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_schedule_step
|
25
|
+
@tl << Event[time: 1.0, actor: @node, action: :foo, x: 1]
|
26
|
+
|
27
|
+
assert_equal 1.0, @tl.step
|
28
|
+
assert_equal 1.0, @tl.now
|
29
|
+
assert_equal 1, @node[:x]
|
30
|
+
|
31
|
+
assert_nil @tl.step
|
32
|
+
assert_equal 1.0, @tl.now
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_schedule_evolve
|
36
|
+
@tl << Event[time: 1.0, actor: @node, action: :foo, x: 1]
|
37
|
+
@tl << Event[time: 2.0, actor: @node, action: :foo, x: 2]
|
38
|
+
@tl << Event[time: 3.0, actor: @node, action: :foo, x: 3]
|
39
|
+
|
40
|
+
assert_equal 1.0, @tl.evolve(1.0)
|
41
|
+
assert_equal 1.0, @tl.now
|
42
|
+
assert_equal 1, @node[:x]
|
43
|
+
|
44
|
+
assert_equal 3.0, @tl.evolve(2.0)
|
45
|
+
assert_equal 3.0, @tl.now
|
46
|
+
assert_equal 3, @node[:x]
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_schedule_in_past
|
50
|
+
@tl << Event[time: 1.0, actor: @node, action: :foo, x: 1]
|
51
|
+
@tl.step
|
52
|
+
|
53
|
+
@tl << Event[time: 0.9, actor: @node, action: :foo, x: 2]
|
54
|
+
assert_raises Spinoza::Timeline::Error do
|
55
|
+
@tl.step
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/test/test-transaction.rb
CHANGED
@@ -2,36 +2,93 @@ require 'minitest/autorun'
|
|
2
2
|
require 'spinoza/system/node'
|
3
3
|
require 'spinoza/transaction'
|
4
4
|
|
5
|
-
include Spinoza
|
6
|
-
|
7
5
|
class TestTransaction < Minitest::Test
|
6
|
+
include Spinoza
|
7
|
+
|
8
8
|
def setup
|
9
|
-
@node = Node
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def test_txn
|
15
|
-
txn = Transaction.new do
|
9
|
+
@node = Node[
|
10
|
+
Table[:foos, id: "integer", name: "string", len: "float"]
|
11
|
+
]
|
12
|
+
|
13
|
+
@txn1 = transaction do
|
16
14
|
at(:foos).insert id: 1, name: "a", len: 1.2
|
17
15
|
at(:foos).insert id: 2, name: "b", len: 3.4
|
16
|
+
end
|
17
|
+
|
18
|
+
@txn2 = transaction do
|
19
|
+
at(:foos, id: 1).read
|
18
20
|
at(:foos, id: 2).read
|
19
|
-
at(:foos
|
21
|
+
at(:foos, id: 3).read
|
22
|
+
at(:foos, id: 1).update len: 1.23
|
20
23
|
at(:foos, id: 2).delete
|
24
|
+
at(:foos).insert id: 3, name: "c", len: 5.6
|
25
|
+
end
|
26
|
+
|
27
|
+
@txn3 = transaction do
|
28
|
+
at(:foos, id: 1).read
|
21
29
|
at(:foos, id: 2).read
|
22
|
-
at(:foos, id: 3).update len: 7.8
|
23
30
|
at(:foos, id: 3).read
|
24
31
|
end
|
25
|
-
|
26
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_txn
|
35
|
+
rslt = @node.store.execute(*@txn1.ops)
|
36
|
+
assert_equal(0, rslt.size)
|
37
|
+
|
38
|
+
rslt = @node.store.execute(*@txn2.ops)
|
39
|
+
assert_equal(3, rslt.size)
|
40
|
+
|
41
|
+
assert_equal({id: 1, name: "a", len: 1.2}, rslt[0].val)
|
42
|
+
assert_equal({id: 2, name: "b", len: 3.4}, rslt[1].val)
|
43
|
+
assert_equal(nil, rslt[2].val)
|
44
|
+
|
45
|
+
rslt = @node.store.execute(*@txn3.ops)
|
27
46
|
assert_equal(3, rslt.size)
|
28
47
|
|
29
|
-
assert_equal(1, rslt[0].val
|
30
|
-
assert_equal(
|
48
|
+
assert_equal({id: 1, name: "a", len: 1.23}, rslt[0].val)
|
49
|
+
assert_equal(nil, rslt[1].val)
|
50
|
+
assert_equal({id: 3, name: "c", len: 5.6}, rslt[2].val)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_read_and_write_sets
|
54
|
+
assert_equal({}, @txn1.read_set)
|
55
|
+
assert_equal({foos: Set[Transaction::INSERT_KEY]}, @txn1.write_set)
|
56
|
+
assert_equal(Set[], @txn1.read_tables)
|
57
|
+
assert_equal(Set[:foos], @txn1.write_tables)
|
31
58
|
|
32
|
-
assert_equal(
|
59
|
+
assert_equal({foos: Set[{id: 1}, {id: 2}, {id: 3}]}, @txn2.read_set)
|
60
|
+
assert_equal({foos: Set[Transaction::INSERT_KEY, {id: 1}, {id: 2}]},
|
61
|
+
@txn2.write_set)
|
62
|
+
assert_equal(Set[:foos], @txn2.read_tables)
|
63
|
+
assert_equal(Set[:foos], @txn2.write_tables)
|
33
64
|
|
34
|
-
assert_equal(1,
|
35
|
-
assert_equal({
|
65
|
+
assert_equal({foos: Set[{id: 1}, {id: 2}, {id: 3}]}, @txn3.read_set)
|
66
|
+
assert_equal({}, @txn3.write_set)
|
67
|
+
assert_equal(Set[:foos], @txn3.read_tables)
|
68
|
+
assert_equal(Set[], @txn3.write_tables)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_all_read_ops
|
72
|
+
assert_equal(3, @txn2.all_read_ops.size)
|
73
|
+
assert_equal([{id: 1}, {id: 2}, {id: 3}],
|
74
|
+
@txn2.all_read_ops.map {|op| op.key})
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_all_write_ops
|
78
|
+
assert_equal(3, @txn2.all_write_ops.size)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_active
|
82
|
+
node2 = Node[
|
83
|
+
Table[:foos, id: "integer", name: "string", len: "float"],
|
84
|
+
Table[:bars, id: "integer", name: "string", len: "float"]
|
85
|
+
]
|
86
|
+
|
87
|
+
txn = transaction do
|
88
|
+
at(:bars).insert id: 1, name: "a", len: 1.2
|
89
|
+
end
|
90
|
+
|
91
|
+
refute txn.active? @node
|
92
|
+
assert txn.active? node2
|
36
93
|
end
|
37
94
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinoza
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel VanderWerf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rbtree
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Model of Calvin distributed database.
|
42
56
|
email: vjoel@users.sourceforge.net
|
43
57
|
executables: []
|
@@ -49,16 +63,33 @@ files:
|
|
49
63
|
- COPYING
|
50
64
|
- README.md
|
51
65
|
- Rakefile
|
66
|
+
- lib/spinoza/calvin/executor.rb
|
67
|
+
- lib/spinoza/calvin/node.rb
|
68
|
+
- lib/spinoza/calvin/readcaster.rb
|
69
|
+
- lib/spinoza/calvin/scheduler.rb
|
70
|
+
- lib/spinoza/calvin/sequencer.rb
|
52
71
|
- lib/spinoza/common.rb
|
53
72
|
- lib/spinoza/system/link.rb
|
54
73
|
- lib/spinoza/system/lock-manager.rb
|
74
|
+
- lib/spinoza/system/log.rb
|
75
|
+
- lib/spinoza/system/meta-log.rb
|
76
|
+
- lib/spinoza/system/model.rb
|
55
77
|
- lib/spinoza/system/node.rb
|
56
78
|
- lib/spinoza/system/operation.rb
|
57
79
|
- lib/spinoza/system/store.rb
|
58
|
-
- lib/spinoza/system/table
|
80
|
+
- lib/spinoza/system/table.rb
|
81
|
+
- lib/spinoza/system/timeline.rb
|
59
82
|
- lib/spinoza/transaction.rb
|
60
83
|
- lib/spinoza/version.rb
|
84
|
+
- test/test-executor.rb
|
85
|
+
- test/test-link.rb
|
86
|
+
- test/test-log.rb
|
87
|
+
- test/test-meta-log.rb
|
61
88
|
- test/test-node.rb
|
89
|
+
- test/test-readcaster.rb
|
90
|
+
- test/test-scheduler.rb
|
91
|
+
- test/test-sequencer.rb
|
92
|
+
- test/test-timeline.rb
|
62
93
|
- test/test-transaction.rb
|
63
94
|
homepage: https://github.com/vjoel/spinoza
|
64
95
|
licenses:
|
@@ -92,6 +123,14 @@ signing_key:
|
|
92
123
|
specification_version: 4
|
93
124
|
summary: Model of Calvin distributed database.
|
94
125
|
test_files:
|
126
|
+
- test/test-executor.rb
|
127
|
+
- test/test-timeline.rb
|
128
|
+
- test/test-link.rb
|
95
129
|
- test/test-node.rb
|
130
|
+
- test/test-sequencer.rb
|
131
|
+
- test/test-meta-log.rb
|
132
|
+
- test/test-scheduler.rb
|
133
|
+
- test/test-readcaster.rb
|
134
|
+
- test/test-log.rb
|
96
135
|
- test/test-transaction.rb
|
97
136
|
has_rdoc:
|