perobs 2.3.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|