perobs 4.4.0 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/perobs/BigArrayNode.rb +10 -8
- data/lib/perobs/Cache.rb +13 -0
- data/lib/perobs/Log.rb +5 -0
- data/lib/perobs/Store.rb +16 -2
- data/lib/perobs/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90c77003da7bd628fa753bfe35918d8c702b433ac5113ba9fc206f7afa114f6c
|
4
|
+
data.tar.gz: c38f786cb10a040048b7d08b75c16baf034c116a3f9648ece3af7b50e7898446
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fea934c359190c3b171c99e4dbffb3af58ec2f9dd755eedc0acb7db556f0e2471bd3c527a2910e5d8f17cd59b3f1ca4079436bc80bd11ea5d6efa60f55a54e9
|
7
|
+
data.tar.gz: db71320a9672848a3e35088e7a8b3389278c987a1bea905336e3f8bfff6daeb27564724b6f9d681d364684a57ce8593021041626615dace155e1849b0944003b
|
data/lib/perobs/BigArrayNode.rb
CHANGED
@@ -135,27 +135,29 @@ module PEROBS
|
|
135
135
|
node = self
|
136
136
|
|
137
137
|
# Traverse the tree to find the right node to add or replace the value.
|
138
|
+
idx = index
|
138
139
|
while node do
|
139
140
|
# Once we have reached a leaf node we can insert or replace the value.
|
140
141
|
if node.is_leaf?
|
141
|
-
if
|
142
|
+
if idx >= node.values.size
|
142
143
|
node.fatal "Set index (#{index}) larger than values array " +
|
143
|
-
"(#{node.values.size})."
|
144
|
+
"(#{idx} >= #{node.values.size})."
|
144
145
|
end
|
145
|
-
node.values[
|
146
|
+
node.values[idx] = value
|
146
147
|
return
|
147
148
|
else
|
148
149
|
# Descend into the right child node to add the value to.
|
149
|
-
cidx = node.search_child_index(
|
150
|
-
if (
|
151
|
-
node.fatal "
|
150
|
+
cidx = node.search_child_index(idx)
|
151
|
+
if (idx -= node.offsets[cidx]) < 0
|
152
|
+
node.fatal "Idx (#{idx}) became negative while looking for " +
|
153
|
+
"index #{index}."
|
152
154
|
end
|
153
155
|
node = node.children[cidx]
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
157
159
|
node.fatal "Could not find proper node to set the value while " +
|
158
|
-
"looking for index #{index}"
|
160
|
+
"looking for index #{index}."
|
159
161
|
end
|
160
162
|
|
161
163
|
# Insert the given value at the given index. All following values will be
|
@@ -811,7 +813,7 @@ module PEROBS
|
|
811
813
|
|
812
814
|
# Print and log an error message for the node.
|
813
815
|
def fatal(msg)
|
814
|
-
msg = "Fatal error in BigArray node @#{@_id}: #{msg}\n"
|
816
|
+
msg = "Fatal error in BigArray node @#{@_id}: #{msg}\n"
|
815
817
|
$stderr.puts msg
|
816
818
|
PEROBS.log.fatal msg
|
817
819
|
end
|
data/lib/perobs/Cache.rb
CHANGED
@@ -165,10 +165,20 @@ module PEROBS
|
|
165
165
|
# active, the write cache is flushed before the transaction is started.
|
166
166
|
def begin_transaction
|
167
167
|
if @transaction_stack.empty?
|
168
|
+
if @transaction_thread
|
169
|
+
PEROBS.log.fatal 'transaction_thread must be nil'
|
170
|
+
end
|
171
|
+
@transaction_thread = Thread.current
|
168
172
|
# The new transaction is the top-level transaction. Flush the write
|
169
173
|
# buffer to save the current state of all objects.
|
170
174
|
flush
|
171
175
|
else
|
176
|
+
# Nested transactions are currently only supported within the same
|
177
|
+
# thread. If we are in another thread, raise TransactionInOtherThread
|
178
|
+
# to pause the calling thread for a bit.
|
179
|
+
if @transaction_thread != Thread.current
|
180
|
+
raise TransactionInOtherThread
|
181
|
+
end
|
172
182
|
# Save a copy of all objects that were modified during the enclosing
|
173
183
|
# transaction.
|
174
184
|
@transaction_stack.last.each do |id|
|
@@ -192,6 +202,7 @@ module PEROBS
|
|
192
202
|
# into the backend storage.
|
193
203
|
@transaction_stack.pop.each { |id| @transaction_objects[id]._sync }
|
194
204
|
@transaction_objects = ::Hash.new
|
205
|
+
@transaction_thread = nil
|
195
206
|
else
|
196
207
|
# A nested transaction completed successfully. We add the list of
|
197
208
|
# modified objects to the list of the enclosing transaction.
|
@@ -213,6 +224,7 @@ module PEROBS
|
|
213
224
|
@transaction_stack.pop.each do |id|
|
214
225
|
@transaction_objects[id]._restore(@transaction_stack.length)
|
215
226
|
end
|
227
|
+
@transaction_thread = nil
|
216
228
|
end
|
217
229
|
|
218
230
|
# Clear all cached entries. You must call flush before calling this
|
@@ -224,6 +236,7 @@ module PEROBS
|
|
224
236
|
@reads = ::Array.new(2 ** @bits)
|
225
237
|
@writes = ::Array.new(2 ** @bits)
|
226
238
|
@transaction_stack = ::Array.new
|
239
|
+
@transaction_thread = nil
|
227
240
|
@transaction_objects = ::Hash.new
|
228
241
|
end
|
229
242
|
|
data/lib/perobs/Log.rb
CHANGED
@@ -42,6 +42,11 @@ module PEROBS
|
|
42
42
|
# are caused by user error rather than program logic errors.
|
43
43
|
class UsageError < StandardError ; end
|
44
44
|
|
45
|
+
# This is the Exception type that will be thrown when a transaction start
|
46
|
+
# failed because there is an ongoing transaction from another thread in
|
47
|
+
# progress.
|
48
|
+
class TransactionInOtherThread < StandardError ; end
|
49
|
+
|
45
50
|
# The ILogger class is a singleton that provides a common logging mechanism
|
46
51
|
# to all objects. It exposes essentially the same interface as the Logger
|
47
52
|
# class, just as a singleton and extends fatal to raise an FatalError
|
data/lib/perobs/Store.rb
CHANGED
@@ -455,7 +455,21 @@ module PEROBS
|
|
455
455
|
# beginning of the transaction. The exception is passed on to the
|
456
456
|
# enclosing scope, so you probably want to handle it accordingly.
|
457
457
|
def transaction
|
458
|
-
|
458
|
+
transaction_not_started = true
|
459
|
+
while transaction_not_started do
|
460
|
+
begin
|
461
|
+
@lock.synchronize do
|
462
|
+
@cache.begin_transaction
|
463
|
+
# If we get to this point, the transaction was successfully
|
464
|
+
# started. We can exit the loop.
|
465
|
+
transaction_not_started = false
|
466
|
+
end
|
467
|
+
rescue TransactionInOtherThread
|
468
|
+
# sleep up to 50ms
|
469
|
+
sleep(rand(50) / 1000.0)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
459
473
|
begin
|
460
474
|
yield if block_given?
|
461
475
|
rescue => e
|
@@ -547,7 +561,7 @@ module PEROBS
|
|
547
561
|
# Therefor no locking is needed or even possible. The GC can kick in at
|
548
562
|
# any time and we could be anywhere in the code. So there is a small
|
549
563
|
# risk for a race here, but it should not have any serious consequences.
|
550
|
-
if @in_memory_objects[id] == ruby_object_id
|
564
|
+
if @in_memory_objects && @in_memory_objects[id] == ruby_object_id
|
551
565
|
@in_memory_objects.delete(id)
|
552
566
|
@stats[:collected_objects] += 1
|
553
567
|
end
|
data/lib/perobs/version.rb
CHANGED
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: 4.
|
4
|
+
version: 4.5.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: 2022-02
|
11
|
+
date: 2022-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|