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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2c526c97aab15c09f8e8acbcb432203e7d60fef8c504df6ddb0b8f35459cca0
4
- data.tar.gz: ad077bb879c041289c7a474e87645064ff84203c674640aff59b5f23923ac1b7
3
+ metadata.gz: 90c77003da7bd628fa753bfe35918d8c702b433ac5113ba9fc206f7afa114f6c
4
+ data.tar.gz: c38f786cb10a040048b7d08b75c16baf034c116a3f9648ece3af7b50e7898446
5
5
  SHA512:
6
- metadata.gz: b86fc662ef8bbf623ee7da777f023a74e3db9502df18c45dcda9ce244982225aaec7e74ce25378147c807775765c57d801810ac16be01d2145227bb0642caa3b
7
- data.tar.gz: d0c5a79eb60a1221bc385a1fafbc77a1aaa1e47782b3ea27ca92f5f7c539804bc00a388fdddc1ab956d7805dbdd52d055f5cdd76a8bb155ec5ada4335b7b9175
6
+ metadata.gz: 1fea934c359190c3b171c99e4dbffb3af58ec2f9dd755eedc0acb7db556f0e2471bd3c527a2910e5d8f17cd59b3f1ca4079436bc80bd11ea5d6efa60f55a54e9
7
+ data.tar.gz: db71320a9672848a3e35088e7a8b3389278c987a1bea905336e3f8bfff6daeb27564724b6f9d681d364684a57ce8593021041626615dace155e1849b0944003b
@@ -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 index >= node.values.size
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[index] = value
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(index)
150
- if (index -= node.offsets[cidx]) < 0
151
- node.fatal "Index (#{index}) became negative"
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" + @tree.to_s
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
- @lock.synchronize { @cache.begin_transaction }
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
@@ -1,4 +1,4 @@
1
1
  module PEROBS
2
2
  # The version number
3
- VERSION = "4.4.0"
3
+ VERSION = "4.5.0"
4
4
  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: 4.4.0
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-05 00:00:00.000000000 Z
11
+ date: 2022-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler