Multiple threads read and write to the accounting blocks list causing
data races. Luckily, the LinkedList threw a ConcurrentModificationException
to limit damage. Now, a ReadWriteLock protects the LinkedList against
data races. Multiple threads can read the list at the same time but only
one thread can write to it. Other writing threads wait until it's their
turn.
Fixes#6545
Add a third cache to WalletService, cleared upon wallet change events,
which maps txIds to txs. This allows the speedup of repeated calls to
'WalletService.getConfidenceForTxId', by avoiding the need to copy and
scan the entire set of wallet txs to find the one with matching id,
for each method invocation.
This is mainly to provide a further speedup to the closed-trades-view
load, by making it much faster to filter the list of BSQ swap trades by
tx confirmation status in 'ClosedTradesDataModel.applyList' and
'ClosedTradesManager.getNumPastTrades'.
Reduce a bottleneck in the closed-trades-view load & table scrolling,
caused by a call to 'ClosedTradesManager.getNumPastTrades' for each
list item displayed. This repeatedly scans the entire collection of
closed trades and BSQ swap trades, in order to count all those which
share a given peer node address. (Scanning the BSQ swap trades is
particularly slow due to their filtering by tx confirmation status.)
To this end, cache the counts of trades by peer node address with a
nullable Multiset field in ClosedTradesManager & BsqSwapTradeManager,
so that the trades are scanned at most once when the view loads. Add
listeners to clear the respective cache when the trade list changes or
the BSQ wallet txs change.
Each time when MailboxMessageService.onAdded(...) got called with
multiple mailbox entries a new thread got created. That thread was never
shutdown. This change explicitly creates a new Thread and sets its
result with a SettableFuture. After its computation the thread
terminates.
The DaoStateStorageService submits tasks to a daemon thread executor
service. The JVM continues to execute threads until all non-daemon
threads have terminated. So the JVM will kill the DaoStateStorageService
during write requests leading to data corruption.
This change uses a non-daemon thread executor service at waits during
shutdown until all data is written to disk.
Before SynchronizedProtoOutputStream created a new thread and made a
blocking call to ProtoOutputStream.writeEnvelope(...). Each connection
had an instance of SynchronizedProtoOutputStream, so we had a redundant
thread per connection. This change makes ProtoBufOutputStream
thread-safe and reduces the number of thread per connection as a
side effect.