perobs 2.3.1 → 2.4.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/perobs/Array.rb +17 -4
- data/lib/perobs/BTreeBlob.rb +22 -23
- data/lib/perobs/BTreeDB.rb +11 -12
- data/lib/perobs/Cache.rb +5 -4
- data/lib/perobs/DataBase.rb +19 -7
- data/lib/perobs/DynamoDB.rb +1 -1
- data/lib/perobs/FixedSizeBlobFile.rb +189 -0
- data/lib/perobs/FlatFile.rb +513 -0
- data/lib/perobs/FlatFileDB.rb +249 -0
- data/lib/perobs/FreeSpaceManager.rb +204 -0
- data/lib/perobs/Hash.rb +17 -4
- data/lib/perobs/IndexTree.rb +164 -0
- data/lib/perobs/IndexTreeNode.rb +296 -0
- data/lib/perobs/Log.rb +125 -0
- data/lib/perobs/Object.rb +10 -11
- data/lib/perobs/ObjectBase.rb +18 -5
- data/lib/perobs/StackFile.rb +137 -0
- data/lib/perobs/Store.rb +85 -19
- data/lib/perobs/TreeDB.rb +276 -0
- data/lib/perobs/version.rb +1 -1
- data/test/Array_spec.rb +11 -2
- data/test/FixedSizeBlobFile_spec.rb +91 -0
- data/test/FlatFileDB_spec.rb +56 -0
- data/test/FreeSpaceManager_spec.rb +91 -0
- data/test/Hash_spec.rb +11 -2
- data/test/IndexTree_spec.rb +118 -0
- data/test/Object_spec.rb +29 -17
- data/test/StackFile_spec.rb +113 -0
- data/test/Store_spec.rb +37 -3
- metadata +22 -3
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 by Chris Schlaeger <chris@taskjuggler.org>
|
4
|
+
#
|
5
|
+
# MIT License
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
require 'fileutils'
|
27
|
+
|
28
|
+
require 'spec_helper'
|
29
|
+
require 'perobs/FreeSpaceManager'
|
30
|
+
|
31
|
+
describe PEROBS::FreeSpaceManager do
|
32
|
+
|
33
|
+
before(:all) do
|
34
|
+
@db_dir = generate_db_name('FreeSpaceManager')
|
35
|
+
FileUtils.mkdir_p(@db_dir)
|
36
|
+
@m = PEROBS::FreeSpaceManager.new(@db_dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
after(:all) do
|
40
|
+
FileUtils.rm_rf(@db_dir)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should open the space manager' do
|
44
|
+
@m.open
|
45
|
+
expect(@m.inspect).to eql('[]')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should support adding and removing space' do
|
49
|
+
@m.add_space(1, 7)
|
50
|
+
expect(@m.has_space?(1, 7)).to be true
|
51
|
+
expect(@m.inspect).to eql('[nil, nil, [[1, 7]]]')
|
52
|
+
expect(@m.get_space(4)).to eql([ 1, 7 ])
|
53
|
+
expect(@m.inspect).to eql('[nil, nil, []]')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should no longer provide that space' do
|
57
|
+
expect(@m.get_space(4)).to be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should keep values over an close/open' do
|
61
|
+
@m.add_space(1, 15)
|
62
|
+
@m.close
|
63
|
+
@m.open
|
64
|
+
expect(@m.inspect).to eql('[nil, nil, [], [[1, 15]]]')
|
65
|
+
expect(@m.get_space(8)).to eql([ 1, 15 ])
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should support clearing the data' do
|
69
|
+
@m.clear
|
70
|
+
expect(@m.inspect).to eql('[]')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should multiple values to a pool' do
|
74
|
+
1.upto(8) { |i| @m.add_space(i, i) }
|
75
|
+
expect(@m.inspect).to eql('[[[1, 1]], [[2, 2], [3, 3]], [[4, 4], [5, 5], [6, 6], [7, 7]], [[8, 8]]]')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should return the spaces again' do
|
79
|
+
expect(@m.get_space(1)).to eql([ 1, 1])
|
80
|
+
expect(@m.inspect).to eql('[[], [[2, 2], [3, 3]], [[4, 4], [5, 5], [6, 6], [7, 7]], [[8, 8]]]')
|
81
|
+
expect(@m.get_space(2)).to eql([ 3, 3])
|
82
|
+
expect(@m.inspect).to eql('[[], [[2, 2]], [[4, 4], [5, 5], [6, 6], [7, 7]], [[8, 8]]]')
|
83
|
+
expect(@m.get_space(2)).to eql([ 2, 2])
|
84
|
+
expect(@m.inspect).to eql('[[], [], [[4, 4], [5, 5], [6, 6], [7, 7]], [[8, 8]]]')
|
85
|
+
expect(@m.get_space(4)).to eql([ 7, 7])
|
86
|
+
expect(@m.inspect).to eql('[[], [], [[4, 4], [5, 5], [6, 6]], [[8, 8]]]')
|
87
|
+
expect(@m.get_space(8)).to eql([ 8, 8])
|
88
|
+
expect(@m.inspect).to eql('[[], [], [[4, 4], [5, 5], [6, 6]], []]')
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/test/Hash_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
#
|
3
|
-
# Copyright (c) 2015 by Chris Schlaeger <chris@taskjuggler.org>
|
3
|
+
# Copyright (c) 2015, 2016 by Chris Schlaeger <chris@taskjuggler.org>
|
4
4
|
#
|
5
5
|
# This file contains tests for Hash that are similar to the tests for the
|
6
6
|
# Hash implementation in MRI. The ideas of these tests were replicated in
|
@@ -158,11 +158,20 @@ describe PEROBS::Hash do
|
|
158
158
|
pcheck { expect(h2).to eq(hb) }
|
159
159
|
end
|
160
160
|
|
161
|
+
it 'should support inspect' do
|
162
|
+
h1 = cph({ 1 => 2 })
|
163
|
+
h2 = cph({ 1 => 2, 'h1' => h1 })
|
164
|
+
expect(h1.inspect).to eq("<PEROBS::Hash:#{h1._id}>\n{\n 1 => 2\n}\n")
|
165
|
+
expect(h2.inspect).to eq("<PEROBS::Hash:#{h2._id}>\n{\n 1 => 2,\n \"h1\" => <PEROBS::ObjectBase:#{h1._id}>\n}\n")
|
166
|
+
end
|
167
|
+
|
161
168
|
it 'should catch a leaked PEROBS::ObjectBase object' do
|
162
169
|
@store['a'] = a = @store.new(PEROBS::Hash)
|
163
170
|
o = @store.new(PO)
|
164
171
|
a['a'] = o.get_self
|
165
|
-
|
172
|
+
PEROBS.log.open(StringIO.new)
|
173
|
+
expect { @store.sync }.to raise_error(PEROBS::FatalError)
|
174
|
+
PEROBS.log.open($stderr)
|
166
175
|
end
|
167
176
|
|
168
177
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 by Chris Schlaeger <chris@taskjuggler.org>
|
4
|
+
#
|
5
|
+
# MIT License
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
require 'fileutils'
|
27
|
+
|
28
|
+
require 'spec_helper'
|
29
|
+
require 'perobs/IndexTree'
|
30
|
+
|
31
|
+
describe PEROBS::StackFile do
|
32
|
+
|
33
|
+
before(:all) do
|
34
|
+
@db_dir = generate_db_name('IndexTree')
|
35
|
+
FileUtils.mkdir_p(@db_dir)
|
36
|
+
@t = PEROBS::IndexTree.new(@db_dir)
|
37
|
+
@ref = []
|
38
|
+
end
|
39
|
+
|
40
|
+
after(:all) do
|
41
|
+
FileUtils.rm_rf(@db_dir)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should create the file' do
|
45
|
+
@t.open
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should store and retrieve a value' do
|
49
|
+
@t.put_value(0x8, 8)
|
50
|
+
expect(@t.inspect).to eql("{\n 8 => 8,\n}\n")
|
51
|
+
expect(@t.get_value(0x8)).to eql(8)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should store another value in the same node' do
|
55
|
+
@t.put_value(0x4, 4)
|
56
|
+
expect(@t.get_value(0x4)).to eql(4)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should store another value in a new sub-node' do
|
60
|
+
@t.put_value(0x88, 0x88)
|
61
|
+
expect(@t.inspect).to eql("{\n 4 => 4,\n {\n 8 => 8,\n 136 => 136,\n }\n }\n")
|
62
|
+
expect(@t.get_value(0x88)).to eql(0x88)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should store one more value in a new sub-node' do
|
66
|
+
@t.put_value(0x888, 0x888)
|
67
|
+
expect(@t.inspect).to eql("{\n 4 => 4,\n {\n 8 => 8,\n {\n 136 => 136,\n 2184 => 2184,\n }\n }\n }\n")
|
68
|
+
expect(@t.get_value(0x888)).to eql(0x888)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should delete the 0x88 entry' do
|
72
|
+
expect(@t.delete_value(0x88)).to be true
|
73
|
+
expect(@t.inspect).to eql("{\n 4 => 4,\n {\n 8 => 8,\n {\n 2184 => 2184,\n }\n }\n }\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should delete all other entries' do
|
77
|
+
expect(@t.delete_value(0x8)).to be true
|
78
|
+
expect(@t.delete_value(0x4)).to be true
|
79
|
+
expect(@t.delete_value(0x888)).to be true
|
80
|
+
expect(@t.inspect).to eql("{\n}\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should replace an existing value' do
|
84
|
+
@t.put_value(0x8, 1)
|
85
|
+
@t.put_value(0x8, 2)
|
86
|
+
expect(@t.inspect).to eql("{\n 8 => 2,\n}\n")
|
87
|
+
expect(@t.get_value(0x8)).to eql(2)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should store lots more values' do
|
91
|
+
@ref = [ 28465, 62258, 59640, 40113, 29237, 22890, 43429, 20374, 37393, 48482, 3243, 5751, 23426, 200, 16835, 38979, 31961, 58810, 40284, 53696, 44741, 53939, 16715, 2775, 16708, 49209, 48767, 6138, 36574, 23063, 13374, 33611, 43477, 63753, 22456, 4461, 52257, 62546, 13629, 52716, 54576, 64695, 7514, 22406, 60298, 43935, 50906, 48965, 56244, 12918, 630, 463, 44735, 49868, 10941, 29121, 26034, 21946, 34071, 55514, 35488, 64583, 59245, 43911, 3035, 2848, 3584, 6813, 61754, 877, 28118, 52626, 4454, 19024, 7467, 59573, 7661, 49226, 33151, 25919, 3596, 36407, 41008, 21611, 52627, 6393, 5551, 34773, 26697, 10510, 50726, 7743, 9843, 62188, 24468, 63553, 3728, 60080, 45667, 6165, 38354 ]
|
92
|
+
@ref.each { |v| @t.put_value(v, v) }
|
93
|
+
@ref.each do |v|
|
94
|
+
expect(@t.get_value(v)).to eql(v)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should still have the values after a close/open' do
|
99
|
+
@t.close
|
100
|
+
@t.open
|
101
|
+
@ref.each do |v|
|
102
|
+
expect(@t.get_value(v)).to eql(v)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should delete some of the stored values' do
|
107
|
+
del = [ 55514, 35488, 64583, 59245, 43911, 3035, 2848, 3584, 6813, 61754, 877, 28118, 52626, 4454, 19024, 7467, 23426, 200, 16835, 38979, 31961, 60080, 45667, 6165, 38354 ]
|
108
|
+
del.each do |v|
|
109
|
+
@ref.delete(v)
|
110
|
+
expect(@t.delete_value(v)).to be true
|
111
|
+
end
|
112
|
+
del.each do |v|
|
113
|
+
expect(@t.get_value(v)).to be_nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
data/test/Object_spec.rb
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
require 'spec_helper'
|
27
27
|
require 'perobs'
|
28
28
|
|
29
|
-
class
|
29
|
+
class O1_Object < PEROBS::Object
|
30
30
|
|
31
31
|
po_attr :a1
|
32
32
|
|
@@ -36,7 +36,7 @@ class O1 < PEROBS::Object
|
|
36
36
|
|
37
37
|
end
|
38
38
|
|
39
|
-
class
|
39
|
+
class O2_Object < PEROBS::Object
|
40
40
|
|
41
41
|
po_attr :a1, :a2, :a3, :a4
|
42
42
|
|
@@ -80,8 +80,8 @@ describe PEROBS::Store do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'should initialize attributes with default values' do
|
83
|
-
@store['o1'] = o1 = @store.new(
|
84
|
-
@store['o2'] = o2 = @store.new(
|
83
|
+
@store['o1'] = o1 = @store.new(O1_Object)
|
84
|
+
@store['o2'] = o2 = @store.new(O2_Object)
|
85
85
|
expect(o2.a1).to eq('a1')
|
86
86
|
expect(o2.a2).to be_nil
|
87
87
|
expect(o2.a3).to be_nil
|
@@ -89,8 +89,8 @@ describe PEROBS::Store do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'should assign values to attributes' do
|
92
|
-
@store['o1'] = o1 = @store.new(
|
93
|
-
@store['o2'] = o2 = @store.new(
|
92
|
+
@store['o1'] = o1 = @store.new(O1_Object)
|
93
|
+
@store['o2'] = o2 = @store.new(O2_Object)
|
94
94
|
o1.a1 = 'a1'
|
95
95
|
o2.a1 = nil
|
96
96
|
o2.a3 = o1
|
@@ -103,15 +103,15 @@ describe PEROBS::Store do
|
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'should persist assigned values' do
|
106
|
-
@store['o1'] = o1 = @store.new(
|
107
|
-
@store['o2'] = o2 = @store.new(
|
106
|
+
@store['o1'] = o1 = @store.new(O1_Object)
|
107
|
+
@store['o2'] = o2 = @store.new(O2_Object)
|
108
108
|
o1.a1 = 'a1'
|
109
109
|
o2.a1 = nil
|
110
110
|
o2.a3 = o1
|
111
111
|
o2.a4 = @store.new(PEROBS::Array)
|
112
112
|
o2.a4 += [ 0, 1, 2 ]
|
113
113
|
@store.transaction do
|
114
|
-
@store['o3'] = o3 = @store.new(
|
114
|
+
@store['o3'] = o3 = @store.new(O1_Object)
|
115
115
|
o3.a1 = @store.new(PEROBS::Array)
|
116
116
|
end
|
117
117
|
@store.sync
|
@@ -129,30 +129,42 @@ describe PEROBS::Store do
|
|
129
129
|
expect(o3.a1).to eq([])
|
130
130
|
end
|
131
131
|
|
132
|
+
it 'should support inspect' do
|
133
|
+
o1 = @store.new(O1_Object)
|
134
|
+
o2 = @store.new(O2_Object)
|
135
|
+
o2.a1 = o1
|
136
|
+
expect(o1.inspect).to eq("<O1_Object:#{o1._id}>\n{\n a1 => nil\n}\n")
|
137
|
+
expect(o2.inspect).to eq("<O2_Object:#{o2._id}>\n{\n a1 => <PEROBS::ObjectBase:#{o1._id}>,\n a2 => nil,\n a3 => nil,\n a4 => 42\n}\n")
|
138
|
+
end
|
139
|
+
|
132
140
|
it 'should transparently access a referenced object' do
|
133
|
-
@store['o1'] = o1 = @store.new(
|
134
|
-
@store['o2'] = o2 = @store.new(
|
141
|
+
@store['o1'] = o1 = @store.new(O1_Object)
|
142
|
+
@store['o2'] = o2 = @store.new(O2_Object)
|
135
143
|
o1.a1 = 'a1'
|
136
144
|
o2.a3 = o1
|
137
145
|
expect(o2.a3_deref).to eq('a1')
|
138
146
|
end
|
139
147
|
|
140
148
|
it 'should always return a POXReference for a PEROBS object' do
|
141
|
-
@store['o1'] = o1 = @store.new(
|
142
|
-
o1.a1 = @store.new(
|
149
|
+
@store['o1'] = o1 = @store.new(O1_Object)
|
150
|
+
o1.a1 = @store.new(O2_Object)
|
143
151
|
expect(@store['o1'].respond_to?(:is_poxreference?)).to be true
|
144
152
|
expect(o1.a1.respond_to?(:is_poxreference?)).to be true
|
145
153
|
end
|
146
154
|
|
147
155
|
it 'should catch a leaked PEROBS::ObjectBase object' do
|
148
|
-
@store['a'] = a = @store.new(
|
149
|
-
o = @store.new(
|
150
|
-
|
156
|
+
@store['a'] = a = @store.new(O1_Object)
|
157
|
+
o = @store.new(O2_Object)
|
158
|
+
PEROBS.log.open(StringIO.new)
|
159
|
+
expect { a.a1 = o.get_self }.to raise_error(PEROBS::FatalError)
|
160
|
+
PEROBS.log.open($stderr)
|
151
161
|
end
|
152
162
|
|
153
163
|
it 'should raise an error when no attributes are defined' do
|
154
164
|
@store['o3'] = @store.new(O3)
|
155
|
-
|
165
|
+
PEROBS.log.open(StringIO.new)
|
166
|
+
expect { @store.sync }.to raise_error(PEROBS::FatalError)
|
167
|
+
PEROBS.log.open($stderr)
|
156
168
|
end
|
157
169
|
|
158
170
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 by Chris Schlaeger <chris@taskjuggler.org>
|
4
|
+
#
|
5
|
+
# MIT License
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
require 'fileutils'
|
27
|
+
|
28
|
+
require 'spec_helper'
|
29
|
+
require 'perobs/StackFile'
|
30
|
+
|
31
|
+
describe PEROBS::StackFile do
|
32
|
+
|
33
|
+
before(:all) do
|
34
|
+
@db_dir = generate_db_name('StackFile')
|
35
|
+
FileUtils.mkdir_p(@db_dir)
|
36
|
+
@stack = PEROBS::StackFile.new(@db_dir, 'StackFile', 4)
|
37
|
+
end
|
38
|
+
|
39
|
+
after(:all) do
|
40
|
+
FileUtils.rm_rf(@db_dir)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should create the file' do
|
44
|
+
@stack.open
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not pop an entry from an empty stack' do
|
48
|
+
expect(@stack.pop).to be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should push an entry and pop it again' do
|
52
|
+
@stack.push('1234')
|
53
|
+
expect(@stack.pop).to eql('1234')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should push and pop multiple entries' do
|
57
|
+
@stack.push('1111')
|
58
|
+
@stack.push('2222')
|
59
|
+
@stack.push('3333')
|
60
|
+
@stack.push('4444')
|
61
|
+
expect(@stack.pop).to eql('4444')
|
62
|
+
expect(@stack.pop).to eql('3333')
|
63
|
+
expect(@stack.pop).to eql('2222')
|
64
|
+
expect(@stack.pop).to eql('1111')
|
65
|
+
expect(@stack.pop).to be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should handle mixed pushes and pops' do
|
69
|
+
@stack.push('1111')
|
70
|
+
@stack.push('2222')
|
71
|
+
expect(@stack.pop).to eql('2222')
|
72
|
+
@stack.push('3333')
|
73
|
+
@stack.push('4444')
|
74
|
+
expect(@stack.pop).to eql('4444')
|
75
|
+
expect(@stack.pop).to eql('3333')
|
76
|
+
expect(@stack.pop).to eql('1111')
|
77
|
+
expect(@stack.pop).to be_nil
|
78
|
+
@stack.push('5555')
|
79
|
+
expect(@stack.pop).to eql('5555')
|
80
|
+
@stack.push('6666')
|
81
|
+
@stack.push('7777')
|
82
|
+
expect(@stack.pop).to eql('7777')
|
83
|
+
expect(@stack.pop).to eql('6666')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should persist the stack over close/open' do
|
87
|
+
@stack.push('1111')
|
88
|
+
@stack.push('2222')
|
89
|
+
@stack.close
|
90
|
+
@stack.open
|
91
|
+
expect(@stack.pop).to eql('2222')
|
92
|
+
expect(@stack.pop).to eql('1111')
|
93
|
+
expect(@stack.pop).to be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should iterate over all entries' do
|
97
|
+
@stack.push('1111')
|
98
|
+
@stack.push('2222')
|
99
|
+
@stack.push('3333')
|
100
|
+
s = ''
|
101
|
+
@stack.each { |e| s << e }
|
102
|
+
expect(s).to eql('111122223333')
|
103
|
+
expect(@stack.to_ary).to eql([ '1111', '2222', '3333' ])
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should clear the stack' do
|
107
|
+
@stack.clear
|
108
|
+
expect(@stack.pop).to be_nil
|
109
|
+
expect(@stack.to_ary).to eql([])
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
data/test/Store_spec.rb
CHANGED
@@ -80,6 +80,7 @@ describe PEROBS::Store do
|
|
80
80
|
|
81
81
|
before(:all) do
|
82
82
|
@db_file = generate_db_name(__FILE__)
|
83
|
+
@db_file_new = @db_file + '-new'
|
83
84
|
end
|
84
85
|
|
85
86
|
after(:each) do
|
@@ -436,12 +437,12 @@ describe PEROBS::Store do
|
|
436
437
|
end
|
437
438
|
|
438
439
|
it 'should survive a real world usage test' do
|
439
|
-
options = { :engine => PEROBS::
|
440
|
+
options = { :engine => PEROBS::FlatFileDB }
|
440
441
|
@store = PEROBS::Store.new(@db_file, options)
|
441
442
|
ref = {}
|
442
443
|
|
443
444
|
deletions_since_last_gc = 0
|
444
|
-
0.upto(
|
445
|
+
0.upto(15000) do |i|
|
445
446
|
key = "o#{i}"
|
446
447
|
case rand(8)
|
447
448
|
when 0
|
@@ -467,7 +468,7 @@ describe PEROBS::Store do
|
|
467
468
|
end
|
468
469
|
when 3
|
469
470
|
# Call garbage collector
|
470
|
-
if rand(
|
471
|
+
if rand(60) == 0
|
471
472
|
@store.gc
|
472
473
|
stats = @store.statistics
|
473
474
|
expect(stats.marked_objects).to eq(ref.length)
|
@@ -511,4 +512,37 @@ describe PEROBS::Store do
|
|
511
512
|
end
|
512
513
|
end
|
513
514
|
|
515
|
+
it 'should copy the database' do
|
516
|
+
@store = PEROBS::Store.new(@db_file)
|
517
|
+
@store['person0'] = p0 = @store.new(Person)
|
518
|
+
id0 = p0._id
|
519
|
+
p1 = @store.new(Person)
|
520
|
+
id1 = p1._id
|
521
|
+
p2 = @store.new(Person)
|
522
|
+
id2 = p2._id
|
523
|
+
p1.related = p2
|
524
|
+
p2.related = p1
|
525
|
+
p0.related = p1
|
526
|
+
p3 = @store.new(PEROBS::Array)
|
527
|
+
@store['persons'] = p3
|
528
|
+
p3 << p0
|
529
|
+
p3 << p1
|
530
|
+
p3 << p2
|
531
|
+
p0 = p1 = p2 = p3 = nil
|
532
|
+
expect(@store['person0']._id).to eq(id0)
|
533
|
+
expect(@store['person0'].related._id).to eq(id1)
|
534
|
+
expect(@store['person0'].related.related._id).to eq(id2)
|
535
|
+
|
536
|
+
@store.copy(@db_file_new, { :engine => PEROBS::FlatFileDB })
|
537
|
+
@store.delete_store
|
538
|
+
|
539
|
+
@store = PEROBS::Store.new(@db_file_new, { :engine => PEROBS::FlatFileDB })
|
540
|
+
expect(@store['person0']._id).to eq(id0)
|
541
|
+
expect(@store['person0'].related._id).to eq(id1)
|
542
|
+
expect(@store['person0'].related.related._id).to eq(id2)
|
543
|
+
expect(@store['persons'][0]).to eq(@store['person0'])
|
544
|
+
expect(@store['persons'][1]).to eq(@store['person0'].related)
|
545
|
+
expect(@store['persons'][2]).to eq(@store['person0'].related.related)
|
546
|
+
end
|
547
|
+
|
514
548
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schlaeger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,11 +72,20 @@ files:
|
|
72
72
|
- lib/perobs/ClassMap.rb
|
73
73
|
- lib/perobs/DataBase.rb
|
74
74
|
- lib/perobs/DynamoDB.rb
|
75
|
+
- lib/perobs/FixedSizeBlobFile.rb
|
76
|
+
- lib/perobs/FlatFile.rb
|
77
|
+
- lib/perobs/FlatFileDB.rb
|
78
|
+
- lib/perobs/FreeSpaceManager.rb
|
75
79
|
- lib/perobs/Handle.rb
|
76
80
|
- lib/perobs/Hash.rb
|
81
|
+
- lib/perobs/IndexTree.rb
|
82
|
+
- lib/perobs/IndexTreeNode.rb
|
83
|
+
- lib/perobs/Log.rb
|
77
84
|
- lib/perobs/Object.rb
|
78
85
|
- lib/perobs/ObjectBase.rb
|
86
|
+
- lib/perobs/StackFile.rb
|
79
87
|
- lib/perobs/Store.rb
|
88
|
+
- lib/perobs/TreeDB.rb
|
80
89
|
- lib/perobs/version.rb
|
81
90
|
- perobs.gemspec
|
82
91
|
- tasks/changelog.rake
|
@@ -86,8 +95,13 @@ files:
|
|
86
95
|
- test/Array_spec.rb
|
87
96
|
- test/BTreeDB_spec.rb
|
88
97
|
- test/ClassMap_spec.rb
|
98
|
+
- test/FixedSizeBlobFile_spec.rb
|
99
|
+
- test/FlatFileDB_spec.rb
|
100
|
+
- test/FreeSpaceManager_spec.rb
|
89
101
|
- test/Hash_spec.rb
|
102
|
+
- test/IndexTree_spec.rb
|
90
103
|
- test/Object_spec.rb
|
104
|
+
- test/StackFile_spec.rb
|
91
105
|
- test/Store_spec.rb
|
92
106
|
- test/perobs_spec.rb
|
93
107
|
- test/spec_helper.rb
|
@@ -111,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
125
|
version: '0'
|
112
126
|
requirements: []
|
113
127
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
128
|
+
rubygems_version: 2.2.2
|
115
129
|
signing_key:
|
116
130
|
specification_version: 4
|
117
131
|
summary: Persistent Ruby Object Store
|
@@ -119,8 +133,13 @@ test_files:
|
|
119
133
|
- test/Array_spec.rb
|
120
134
|
- test/BTreeDB_spec.rb
|
121
135
|
- test/ClassMap_spec.rb
|
136
|
+
- test/FixedSizeBlobFile_spec.rb
|
137
|
+
- test/FlatFileDB_spec.rb
|
138
|
+
- test/FreeSpaceManager_spec.rb
|
122
139
|
- test/Hash_spec.rb
|
140
|
+
- test/IndexTree_spec.rb
|
123
141
|
- test/Object_spec.rb
|
142
|
+
- test/StackFile_spec.rb
|
124
143
|
- test/Store_spec.rb
|
125
144
|
- test/perobs_spec.rb
|
126
145
|
- test/spec_helper.rb
|