perobs 3.0.2 → 4.0.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 +18 -17
- data/lib/perobs/BTree.rb +9 -44
- data/lib/perobs/BTreeNode.rb +116 -88
- data/lib/perobs/BTreeNodeCache.rb +10 -8
- data/lib/perobs/BTreeNodeLink.rb +1 -1
- data/lib/perobs/Cache.rb +14 -14
- data/lib/perobs/DynamoDB.rb +1 -1
- data/lib/perobs/EquiBlobsFile.rb +7 -2
- data/lib/perobs/FlatFile.rb +28 -49
- data/lib/perobs/FlatFileBlobHeader.rb +1 -19
- data/lib/perobs/FlatFileDB.rb +5 -0
- data/lib/perobs/LockFile.rb +3 -0
- data/lib/perobs/Object.rb +8 -3
- data/lib/perobs/ObjectBase.rb +6 -4
- data/lib/perobs/PersistentObjectCache.rb +153 -0
- data/lib/perobs/PersistentObjectCacheLine.rb +87 -0
- data/lib/perobs/SpaceTree.rb +5 -3
- data/lib/perobs/SpaceTreeNode.rb +15 -8
- data/lib/perobs/Store.rb +41 -13
- data/lib/perobs/version.rb +1 -1
- data/test/Array_spec.rb +38 -38
- data/test/BTree_spec.rb +45 -0
- data/test/EquiBlobsFile_spec.rb +0 -4
- data/test/FlatFileDB_spec.rb +1 -1
- data/test/Hash_spec.rb +14 -13
- data/test/Object_spec.rb +5 -5
- data/test/Store_spec.rb +62 -19
- data/test/perobs_spec.rb +7 -3
- metadata +4 -3
- data/lib/perobs/SpaceTreeNodeCache.rb +0 -149
data/lib/perobs/version.rb
CHANGED
data/test/Array_spec.rb
CHANGED
@@ -33,7 +33,7 @@ require 'perobs'
|
|
33
33
|
|
34
34
|
class PO < PEROBS::Object
|
35
35
|
|
36
|
-
|
36
|
+
attr_persist :name
|
37
37
|
|
38
38
|
def initialize(store, name = nil)
|
39
39
|
super(store)
|
@@ -65,7 +65,7 @@ describe PEROBS::Array do
|
|
65
65
|
@store.transaction do
|
66
66
|
@store['b'] = @store.new(PEROBS::Array)
|
67
67
|
end
|
68
|
-
@store.
|
68
|
+
@store.exit
|
69
69
|
@store = nil
|
70
70
|
GC.start
|
71
71
|
|
@@ -85,7 +85,7 @@ describe PEROBS::Array do
|
|
85
85
|
expect(a[0]).to eq('A')
|
86
86
|
expect(a[1]).to eq('B')
|
87
87
|
expect(a[2].name).to eq('foobar')
|
88
|
-
@store.
|
88
|
+
@store.exit
|
89
89
|
|
90
90
|
@store = PEROBS::Store.new(@db_name)
|
91
91
|
a = @store['a']
|
@@ -102,7 +102,7 @@ describe PEROBS::Array do
|
|
102
102
|
vs = ''
|
103
103
|
a.each { |v| vs << v }
|
104
104
|
expect(vs).to eq('ABC')
|
105
|
-
@store.
|
105
|
+
@store.exit
|
106
106
|
|
107
107
|
@store = PEROBS::Store.new(@db_name)
|
108
108
|
a = @store['a']
|
@@ -113,15 +113,15 @@ describe PEROBS::Array do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
# Utility method to create a PEROBS::Array from a normal Array.
|
116
|
-
def cpa(ary = nil)
|
116
|
+
def cpa(ary = nil, id = 'a')
|
117
117
|
a = @store.new(PEROBS::Array)
|
118
118
|
a.replace(ary) unless ary.nil?
|
119
|
-
@store[
|
119
|
+
@store[id] = a
|
120
120
|
end
|
121
121
|
|
122
122
|
def pcheck
|
123
123
|
yield
|
124
|
-
@store.
|
124
|
+
@store.exit
|
125
125
|
@store = PEROBS::Store.new(@db_name)
|
126
126
|
yield
|
127
127
|
end
|
@@ -147,44 +147,44 @@ describe PEROBS::Array do
|
|
147
147
|
it 'should support re-writing methods' do
|
148
148
|
x = cpa([2, 5, 3, 1, 7])
|
149
149
|
x.sort!{ |a, b| a <=> b }
|
150
|
-
pcheck { expect(
|
151
|
-
|
152
|
-
pcheck { expect(
|
150
|
+
pcheck { expect(@store['a']).to eq([ 1, 2, 3, 5, 7 ]) }
|
151
|
+
@store['a'].sort!{ |a, b| b - a }
|
152
|
+
pcheck { expect(@store['a']).to eq([ 7, 5, 3, 2, 1 ]) }
|
153
153
|
|
154
|
-
|
155
|
-
pcheck { expect(
|
154
|
+
@store['a'].clear
|
155
|
+
pcheck { expect(@store['a']).to eq([]) }
|
156
156
|
end
|
157
157
|
|
158
158
|
it 'should support <<()' do
|
159
159
|
a = cpa([ 0, 1, 2 ])
|
160
160
|
a << 4
|
161
|
-
pcheck { expect(a).to eq([ 0, 1, 2, 4 ]) }
|
161
|
+
pcheck { expect(@store['a']).to eq([ 0, 1, 2, 4 ]) }
|
162
162
|
end
|
163
163
|
|
164
164
|
it 'should support []=' do
|
165
165
|
a = cpa([ 0, nil, 2 ])
|
166
166
|
a[1] = 1
|
167
|
-
pcheck { expect(a).to eq([ 0, 1, 2 ]) }
|
167
|
+
pcheck { expect(@store['a']).to eq([ 0, 1, 2 ]) }
|
168
168
|
end
|
169
169
|
|
170
170
|
it 'should support collect!()' do
|
171
171
|
a = cpa([ 1, 'cat', 1..1 ])
|
172
|
-
expect(a.collect! { |e| e.class }).to eq([ Integer, String, Range ])
|
173
|
-
pcheck { expect(a).to eq([ Integer, String, Range ]) }
|
172
|
+
expect(a.collect! { |e| e.class.to_s }).to eq([ 'Integer', 'String', 'Range' ])
|
173
|
+
pcheck { expect(@store['a'].to_a).to eq([ 'Integer', 'String', 'Range' ]) }
|
174
174
|
|
175
175
|
a = cpa([ 1, 'cat', 1..1 ])
|
176
176
|
expect(a.collect! { 99 }).to eq([ 99, 99, 99])
|
177
|
-
pcheck { expect(a).to eq([ 99, 99, 99]) }
|
177
|
+
pcheck { expect(@store['a']).to eq([ 99, 99, 99]) }
|
178
178
|
end
|
179
179
|
|
180
180
|
it 'should support map!()' do
|
181
181
|
a = cpa([ 1, 'cat', 1..1 ])
|
182
|
-
expect(a.map! { |e| e.class }).to eq([ Integer, String, Range ])
|
183
|
-
pcheck { expect(a).to eq([ Integer, String, Range ]) }
|
182
|
+
expect(a.map! { |e| e.class.to_s }).to eq([ 'Integer', 'String', 'Range' ])
|
183
|
+
pcheck { expect(@store['a']).to eq([ 'Integer', 'String', 'Range' ]) }
|
184
184
|
|
185
185
|
a = cpa([ 1, 'cat', 1..1 ])
|
186
186
|
expect(a.map! { 99 }).to eq([ 99, 99, 99])
|
187
|
-
pcheck { expect(a).to eq ([ 99, 99, 99]) }
|
187
|
+
pcheck { expect(@store['a']).to eq ([ 99, 99, 99]) }
|
188
188
|
end
|
189
189
|
|
190
190
|
it 'should support fill()' do
|
@@ -194,39 +194,39 @@ describe PEROBS::Array do
|
|
194
194
|
end
|
195
195
|
|
196
196
|
it 'should support flatten!()' do
|
197
|
-
a1 = cpa([ 1, 2, 3])
|
198
|
-
a2 = cpa([ 5, 6 ])
|
199
|
-
a3 = cpa([ 4, a2 ])
|
200
|
-
a4 = cpa([ a1, a3 ])
|
201
|
-
pcheck { expect(a4.flatten).to eq([ 1, 2, 3, 4, 5, 6 ]) }
|
197
|
+
a1 = cpa([ 1, 2, 3], 'a1')
|
198
|
+
a2 = cpa([ 5, 6 ], 'a2')
|
199
|
+
a3 = cpa([ 4, a2 ], 'a3')
|
200
|
+
a4 = cpa([ a1, a3 ], 'a4')
|
201
|
+
pcheck { expect(@store['a4'].flatten).to eq([ 1, 2, 3, 4, 5, 6 ]) }
|
202
202
|
end
|
203
203
|
|
204
204
|
it 'should support replace()' do
|
205
|
-
|
206
|
-
a_id =
|
207
|
-
expect(
|
208
|
-
pcheck { expect(
|
205
|
+
a1 = cpa([ 1, 2, 3], 'a1')
|
206
|
+
a_id = a1.__id__
|
207
|
+
expect(a1.replace(cpa([4, 5, 6], 'a2'))).to eq([ 4, 5, 6 ])
|
208
|
+
pcheck { expect(@store['a1']).to eq ([ 4, 5, 6 ]) }
|
209
209
|
end
|
210
210
|
|
211
211
|
it 'should support insert()' do
|
212
212
|
a = cpa([ 0 ])
|
213
213
|
a.insert(1)
|
214
|
-
pcheck { expect(a).to eq([ 0 ]) }
|
215
|
-
a.insert(1, 1)
|
216
|
-
pcheck { expect(a).to eq([ 0, 1]) }
|
214
|
+
pcheck { expect(@store['a']).to eq([ 0 ]) }
|
215
|
+
@store['a'].insert(1, 1)
|
216
|
+
pcheck { expect(@store['a']).to eq([ 0, 1]) }
|
217
217
|
end
|
218
218
|
|
219
219
|
it 'should support push()' do
|
220
220
|
a = cpa([ 1, 2, 3 ])
|
221
221
|
a.push(4, 5)
|
222
|
-
pcheck { expect(a).to eq([ 1, 2, 3, 4, 5 ]) }
|
223
|
-
a.push(nil)
|
224
|
-
pcheck { expect(a).to eq([ 1, 2, 3, 4, 5, nil ]) }
|
222
|
+
pcheck { expect(@store['a']).to eq([ 1, 2, 3, 4, 5 ]) }
|
223
|
+
@store['a'].push(nil)
|
224
|
+
pcheck { expect(@store['a']).to eq([ 1, 2, 3, 4, 5, nil ]) }
|
225
225
|
end
|
226
226
|
|
227
227
|
it 'should support inspect' do
|
228
|
-
a1 = cpa([ 1 ])
|
229
|
-
a2 = cpa([ 1, a1 ])
|
228
|
+
a1 = cpa([ 1 ], 'a1')
|
229
|
+
a2 = cpa([ 1, a1 ], 'a2')
|
230
230
|
expect(a1.inspect).to eq("<PEROBS::Array:#{a1._id}>\n[\n 1\n]\n")
|
231
231
|
expect(a2.inspect).to eq("<PEROBS::Array:#{a2._id}>\n[\n 1,\n <PEROBS::ObjectBase:#{a1._id}>\n]\n")
|
232
232
|
end
|
@@ -244,7 +244,7 @@ describe PEROBS::Array do
|
|
244
244
|
o = @store.new(PO)
|
245
245
|
a[0] = o.get_self
|
246
246
|
PEROBS.log.open(StringIO.new)
|
247
|
-
expect { @store.
|
247
|
+
expect { @store.exit }.to raise_error(PEROBS::FatalError)
|
248
248
|
PEROBS.log.open($stderr)
|
249
249
|
end
|
250
250
|
|
data/test/BTree_spec.rb
CHANGED
@@ -125,4 +125,49 @@ describe PEROBS::BTree do
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
+
it 'should survive a real-world usage test' do
|
129
|
+
@m.clear
|
130
|
+
ref = {}
|
131
|
+
0.upto(50000) do
|
132
|
+
case rand(5)
|
133
|
+
when 0
|
134
|
+
0.upto(2) do
|
135
|
+
key = rand(100000)
|
136
|
+
value = rand(10000000)
|
137
|
+
@m.insert(key, value)
|
138
|
+
ref[key] = value
|
139
|
+
end
|
140
|
+
when 1
|
141
|
+
if ref.length > 0
|
142
|
+
key = ref.keys[rand(ref.keys.length)]
|
143
|
+
expect(@m.remove(key)).to eql(ref[key])
|
144
|
+
ref.delete(key)
|
145
|
+
end
|
146
|
+
when 2
|
147
|
+
if ref.length > 0
|
148
|
+
0.upto(3) do
|
149
|
+
key = ref.keys[rand(ref.keys.length)]
|
150
|
+
expect(@m.get(key)).to eql(ref[key])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
when 3
|
154
|
+
if ref.length > 0
|
155
|
+
key = ref.keys[rand(ref.keys.length)]
|
156
|
+
value = rand(10000000)
|
157
|
+
@m.insert(key, value)
|
158
|
+
ref[key] = value
|
159
|
+
end
|
160
|
+
when 4
|
161
|
+
if rand(50) == 0
|
162
|
+
expect(@m.check).to be true
|
163
|
+
end
|
164
|
+
when 5
|
165
|
+
if rand(50) == 0
|
166
|
+
@m.close
|
167
|
+
@m.open
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
128
173
|
end
|
data/test/EquiBlobsFile_spec.rb
CHANGED
@@ -179,10 +179,6 @@ describe PEROBS::EquiBlobsFile do
|
|
179
179
|
expect(@bf.check).to be true
|
180
180
|
end
|
181
181
|
|
182
|
-
it 'should not allow erase when open' do
|
183
|
-
expect{ capture_io{ @bf.erase } }.to raise_error(PEROBS::FatalError)
|
184
|
-
end
|
185
|
-
|
186
182
|
it 'should support erasing the file' do
|
187
183
|
@bf.close
|
188
184
|
@bf.erase
|
data/test/FlatFileDB_spec.rb
CHANGED
data/test/Hash_spec.rb
CHANGED
@@ -34,7 +34,7 @@ require 'perobs'
|
|
34
34
|
|
35
35
|
class PO < PEROBS::Object
|
36
36
|
|
37
|
-
|
37
|
+
attr_persist :name
|
38
38
|
|
39
39
|
def initialize(store, name = nil)
|
40
40
|
super(store)
|
@@ -71,7 +71,7 @@ describe PEROBS::Hash do
|
|
71
71
|
|
72
72
|
expect(h['a']).to eq('A')
|
73
73
|
expect(h['b']).to eq('B')
|
74
|
-
@store.
|
74
|
+
@store.exit
|
75
75
|
|
76
76
|
@store = PEROBS::Store.new(@db_name)
|
77
77
|
h = @store['h']
|
@@ -88,6 +88,7 @@ describe PEROBS::Hash do
|
|
88
88
|
vs = []
|
89
89
|
h.each { |k, v| vs << k + v }
|
90
90
|
expect(vs.sort.join).to eq('aAbBcC')
|
91
|
+
@store.exit
|
91
92
|
|
92
93
|
@store = PEROBS::Store.new(@db_name)
|
93
94
|
@store['h'] = h = @store.new(PEROBS::Hash)
|
@@ -100,15 +101,15 @@ describe PEROBS::Hash do
|
|
100
101
|
end
|
101
102
|
|
102
103
|
# Utility method to create a PEROBS::Hash from a normal Hash.
|
103
|
-
def cph(hash = nil)
|
104
|
+
def cph(hash = nil, id = 'a')
|
104
105
|
a = @store.new(PEROBS::Hash)
|
105
106
|
a.replace(hash) unless hash.nil?
|
106
|
-
@store[
|
107
|
+
@store[id] = a
|
107
108
|
end
|
108
109
|
|
109
110
|
def pcheck
|
110
111
|
yield
|
111
|
-
@store.
|
112
|
+
@store.exit
|
112
113
|
@store = PEROBS::Store.new(@db_name)
|
113
114
|
yield
|
114
115
|
end
|
@@ -142,20 +143,20 @@ describe PEROBS::Hash do
|
|
142
143
|
end
|
143
144
|
|
144
145
|
it 'should support merge!' do
|
145
|
-
h1 = cph({ 1 => 2, 2 => 3, 3 => 4 })
|
146
|
-
h2 = cph({ 2 => 'two', 4 => 'four' })
|
146
|
+
h1 = cph({ '1' => 2, '2' => 3, '3' => 4 }, 'h1')
|
147
|
+
h2 = cph({ '2' => 'two', '4' => 'four' }, 'h2')
|
147
148
|
|
148
|
-
ha = { 1 => 2, 2 => 'two', 3 => 4, 4 => 'four' }
|
149
|
-
hb = { 1 => 2, 2 => 3, 3 => 4, 4 => 'four' }
|
149
|
+
ha = { '1' => 2, '2' => 'two', '3' => 4, '4' => 'four' }
|
150
|
+
hb = { '1' => 2, '2' => 3, '3' => 4, '4' => 'four' }
|
150
151
|
|
151
152
|
expect(h1.update(h2)).to eq(ha)
|
152
|
-
pcheck { expect(h1).to eq(ha) }
|
153
|
+
pcheck { expect(@store['h1'].to_hash).to eq(ha) }
|
153
154
|
|
154
|
-
h1 = cph({ 1 => 2, 2 => 3, 3 => 4 })
|
155
|
-
h2 = cph({ 2 => 'two', 4 => 'four' })
|
155
|
+
h1 = cph({ '1' => 2, '2' => 3, '3' => 4 }, 'h1')
|
156
|
+
h2 = cph({ '2' => 'two', '4' => 'four' }, 'h2')
|
156
157
|
|
157
158
|
expect(h2.update(h1)).to eq(hb)
|
158
|
-
pcheck { expect(h2).to eq(hb) }
|
159
|
+
pcheck { expect(@store['h2'].to_hash).to eq(hb) }
|
159
160
|
end
|
160
161
|
|
161
162
|
it 'should support inspect' do
|
data/test/Object_spec.rb
CHANGED
@@ -28,7 +28,7 @@ require 'perobs'
|
|
28
28
|
|
29
29
|
class O1_Object < PEROBS::Object
|
30
30
|
|
31
|
-
|
31
|
+
attr_persist :a1
|
32
32
|
|
33
33
|
def initialize(store)
|
34
34
|
super
|
@@ -38,7 +38,7 @@ end
|
|
38
38
|
|
39
39
|
class O2_Object < PEROBS::Object
|
40
40
|
|
41
|
-
|
41
|
+
attr_persist :a1, :a2, :a3, :a4
|
42
42
|
|
43
43
|
def initialize(store)
|
44
44
|
super
|
@@ -99,7 +99,7 @@ describe PEROBS::Store do
|
|
99
99
|
expect(o2.a1).to be_nil
|
100
100
|
expect(o2.a3).to eq(o1)
|
101
101
|
expect(o2.a4).to eq(42)
|
102
|
-
@store.
|
102
|
+
@store.exit
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'should persist assigned values' do
|
@@ -114,7 +114,7 @@ describe PEROBS::Store do
|
|
114
114
|
@store['o3'] = o3 = @store.new(O1_Object)
|
115
115
|
o3.a1 = @store.new(PEROBS::Array)
|
116
116
|
end
|
117
|
-
@store.
|
117
|
+
@store.exit
|
118
118
|
@store = nil
|
119
119
|
GC.start
|
120
120
|
|
@@ -163,7 +163,7 @@ describe PEROBS::Store do
|
|
163
163
|
it 'should raise an error when no attributes are defined' do
|
164
164
|
@store['o3'] = @store.new(O3)
|
165
165
|
PEROBS.log.open(StringIO.new)
|
166
|
-
expect { @store.
|
166
|
+
expect { @store.exit }.to raise_error(PEROBS::FatalError)
|
167
167
|
PEROBS.log.open($stderr)
|
168
168
|
end
|
169
169
|
|
data/test/Store_spec.rb
CHANGED
@@ -31,7 +31,7 @@ end
|
|
31
31
|
|
32
32
|
class Person < PEROBS::Object
|
33
33
|
|
34
|
-
|
34
|
+
attr_persist :name, :zip, :bmi, :married, :related, :relatives
|
35
35
|
|
36
36
|
def initialize(store)
|
37
37
|
super
|
@@ -44,7 +44,7 @@ end
|
|
44
44
|
|
45
45
|
class PersonN < PEROBS::Object
|
46
46
|
|
47
|
-
|
47
|
+
attr_persist :name, :zip, :bmi, :married, :related, :relatives
|
48
48
|
|
49
49
|
def initialize(store)
|
50
50
|
super
|
@@ -57,7 +57,7 @@ end
|
|
57
57
|
|
58
58
|
class O0 < PEROBS::Object
|
59
59
|
|
60
|
-
|
60
|
+
attr_persist :child
|
61
61
|
|
62
62
|
def initialize(store)
|
63
63
|
super
|
@@ -67,7 +67,7 @@ class O0 < PEROBS::Object
|
|
67
67
|
end
|
68
68
|
class O1 < PEROBS::Object
|
69
69
|
|
70
|
-
|
70
|
+
attr_persist :parent
|
71
71
|
|
72
72
|
def initialize(store, p = nil)
|
73
73
|
super(store)
|
@@ -130,7 +130,7 @@ describe PEROBS::Store do
|
|
130
130
|
jane.married = true
|
131
131
|
jane.relatives = 'test'
|
132
132
|
|
133
|
-
@store.
|
133
|
+
@store.exit
|
134
134
|
|
135
135
|
@store = PEROBS::Store.new(@db_file)
|
136
136
|
john = @store['john']
|
@@ -175,7 +175,7 @@ describe PEROBS::Store do
|
|
175
175
|
jane.married = true
|
176
176
|
jane.relatives = 'test'
|
177
177
|
|
178
|
-
@store.
|
178
|
+
@store.exit
|
179
179
|
|
180
180
|
@store = PEROBS::Store.new(@db_file)
|
181
181
|
@store.rename_classes({ 'Person' => 'PersonN' })
|
@@ -200,7 +200,7 @@ describe PEROBS::Store do
|
|
200
200
|
0.upto(20) do |i|
|
201
201
|
@store["person#{i}"].name = "New Person #{i}"
|
202
202
|
end
|
203
|
-
@store.
|
203
|
+
@store.exit
|
204
204
|
@store = PEROBS::Store.new(@db_file)
|
205
205
|
0.upto(20) do |i|
|
206
206
|
expect(@store["person#{i}"].name).to eq("New Person #{i}")
|
@@ -218,6 +218,7 @@ describe PEROBS::Store do
|
|
218
218
|
@store.sync
|
219
219
|
@store['person1'] = nil
|
220
220
|
@store.gc
|
221
|
+
@store.exit
|
221
222
|
@store = PEROBS::Store.new(@db_file)
|
222
223
|
expect(@store.object_by_id(id1)).to be_nil
|
223
224
|
expect(@store['person2']._id).to eq(id2)
|
@@ -238,6 +239,7 @@ describe PEROBS::Store do
|
|
238
239
|
expect(@store.check).to eq(0)
|
239
240
|
expect(@store.gc).to eq(0)
|
240
241
|
p0 = p1 = p2 = nil
|
242
|
+
@store.exit
|
241
243
|
GC.start
|
242
244
|
@store = PEROBS::Store.new(@db_file)
|
243
245
|
expect(@store['person0']._id).to eq(id0)
|
@@ -249,6 +251,7 @@ describe PEROBS::Store do
|
|
249
251
|
GC.start
|
250
252
|
expect(@store.object_by_id(id1)).to be_nil
|
251
253
|
expect(@store.object_by_id(id2)).to be_nil
|
254
|
+
@store.exit
|
252
255
|
|
253
256
|
@store = PEROBS::Store.new(@db_file)
|
254
257
|
expect(@store.check).to eq(0)
|
@@ -432,43 +435,83 @@ describe PEROBS::Store do
|
|
432
435
|
@store['root'] = @store.new(O0)
|
433
436
|
@store.sync
|
434
437
|
expect(@store.check).to eq(0)
|
438
|
+
@store.exit
|
435
439
|
|
436
440
|
@store = PEROBS::Store.new(@db_file)
|
437
441
|
expect(@store.check).to eq(0)
|
438
442
|
expect(@store['root'].child.parent).to eq(@store['root'])
|
439
443
|
end
|
440
444
|
|
445
|
+
it 'should handle frequent updates of objects' do
|
446
|
+
@store = PEROBS::Store.new(@db_file)
|
447
|
+
count = 10000
|
448
|
+
0.upto(count) do |i|
|
449
|
+
key = "Obj#{i}"
|
450
|
+
@store[key] = p = @store.new(Person)
|
451
|
+
p.name = "0:#{i}:" + 'X' * rand(64)
|
452
|
+
end
|
453
|
+
|
454
|
+
0.upto(10) do |iteration|
|
455
|
+
0.upto(count) do |i|
|
456
|
+
key = "Obj#{i}"
|
457
|
+
p = @store[key]
|
458
|
+
p.name = "#{iteration}:#{i}:" + 'X' * rand(64)
|
459
|
+
end
|
460
|
+
0.upto(count) do |i|
|
461
|
+
key = "Obj#{i}"
|
462
|
+
p = @store[key]
|
463
|
+
o_it, o_i, o_x = p.name.split(':')
|
464
|
+
if o_it.to_i != iteration
|
465
|
+
$stderr.puts "Mismatch of #{p._id} with value #{o_it}:#{i}"
|
466
|
+
end
|
467
|
+
expect(o_it.to_i).to eql(iteration)
|
468
|
+
expect(o_i.to_i).to eql(i)
|
469
|
+
end
|
470
|
+
@store.check
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
441
474
|
it 'should survive a real world usage test' do
|
442
475
|
options = { :engine => PEROBS::FlatFileDB }
|
443
476
|
@store = PEROBS::Store.new(@db_file, options)
|
444
477
|
ref = {}
|
445
478
|
|
446
479
|
deletions_since_last_gc = 0
|
447
|
-
0.upto(
|
480
|
+
0.upto(10000) do |i|
|
448
481
|
key = "o#{i}"
|
449
|
-
case rand(
|
482
|
+
case rand(9)
|
450
483
|
when 0
|
451
484
|
# Add 'A' person
|
452
|
-
value = 'A' * rand(512)
|
485
|
+
value = key + 'A' * rand(512)
|
453
486
|
@store[key] = p = @store.new(Person)
|
454
487
|
p.name = value
|
455
488
|
ref[key] = value
|
456
489
|
when 1
|
457
490
|
# Add 'B' person
|
458
|
-
value = 'B' * rand(
|
491
|
+
value = key + 'B' * rand(32)
|
459
492
|
@store[key] = p = @store.new(Person)
|
460
493
|
p.name = value
|
461
494
|
ref[key] = value
|
462
495
|
when 2
|
463
496
|
# Delete a root entry
|
464
497
|
if ref.keys.length > 11
|
465
|
-
key = ref.keys[(ref.keys.length
|
498
|
+
key = ref.keys[rand(ref.keys.length)]
|
466
499
|
expect(@store[key]).not_to be_nil
|
467
500
|
@store[key] = nil
|
468
501
|
ref.delete(key)
|
469
502
|
deletions_since_last_gc += 1
|
470
503
|
end
|
471
504
|
when 3
|
505
|
+
# Update a person entry
|
506
|
+
if ref.keys.length > 0
|
507
|
+
key = ref.keys[rand(ref.keys.length)]
|
508
|
+
expect(@store[key]).not_to be_nil
|
509
|
+
value = key + 'C' * rand(996)
|
510
|
+
p = @store[key]
|
511
|
+
p.name = value
|
512
|
+
ref[key] = value
|
513
|
+
end
|
514
|
+
when 4
|
472
515
|
# Call garbage collector
|
473
516
|
if rand(60) == 0
|
474
517
|
@store.gc
|
@@ -478,32 +521,32 @@ describe PEROBS::Store do
|
|
478
521
|
deletions_since_last_gc = 0
|
479
522
|
expect(@store.gc).to eq(deletions_since_last_gc)
|
480
523
|
end
|
481
|
-
when
|
524
|
+
when 5
|
482
525
|
# Sync store and reload
|
483
526
|
if rand(15) == 0
|
484
527
|
@store.exit
|
485
528
|
@store = PEROBS::Store.new(@db_file, options)
|
486
529
|
end
|
487
|
-
when
|
530
|
+
when 6
|
488
531
|
# Replace an entry with 'C' person
|
489
532
|
if ref.keys.length > 13
|
490
533
|
key = ref.keys[(ref.keys.length / 13).to_i]
|
491
|
-
value = '
|
534
|
+
value = key + 'D' * rand(1024)
|
492
535
|
@store[key] = p = @store.new(Person)
|
493
536
|
p.name = value
|
494
537
|
ref[key] = value
|
495
538
|
deletions_since_last_gc += 1
|
496
539
|
end
|
497
|
-
when
|
540
|
+
when 7
|
498
541
|
# Sync and check store
|
499
542
|
if rand(50) == 0
|
500
|
-
|
543
|
+
#@store.sync
|
501
544
|
expect(@store.check(false)).to eq(0)
|
502
545
|
end
|
503
|
-
when
|
546
|
+
when 8
|
504
547
|
# Compare a random entry with reference entry
|
505
548
|
if ref.keys.length > 0
|
506
|
-
key = ref.keys[rand(ref.keys.length
|
549
|
+
key = ref.keys[rand(ref.keys.length)]
|
507
550
|
expect(@store[key].name).to eq(ref[key])
|
508
551
|
end
|
509
552
|
end
|