Potential HSQLDB deadlock fix

After opening repository connection with RepositoryManager.getRepostory(),
any 'read' from repository (e.g. SELECT) starts the transaction
even though HSQLDB documentation states there are no shared/read locks
in MVCC concurrency model.

The work-around for this is to 'reset' HSQLDB's in-transaction flag
by performing a ROLLBACK (Repository.discardChanges) immediately
after acquiring the blockchain lock (which is used to ringfence
changes that might collide like these).

Also adding an extra check to prevent payments to nonexistent AT
addresses as it touches Transaction.
This commit is contained in:
catbref
2019-04-29 15:18:44 +01:00
parent b21ef18533
commit a316b8a810
8 changed files with 161 additions and 67 deletions

View File

@@ -1,6 +1,8 @@
package org.qora.test;
import org.junit.Test;
import org.qora.account.Account;
import org.qora.asset.Asset;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.RepositoryManager;
@@ -8,6 +10,8 @@ import org.qora.test.common.Common;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -55,4 +59,31 @@ public class RepositoryTests extends Common {
}
}
@Test
public void testDeadlock() throws DataException {
Common.useDefaultSettings();
// Open connection 1
try (Repository repository1 = RepositoryManager.getRepository()) {
// Do a database 'read'
Account account1 = Common.getTestAccount(repository1, "alice");
account1.getLastReference();
// Open connection 2
try (Repository repository2 = RepositoryManager.getRepository()) {
// Update account in 2
Account account2 = Common.getTestAccount(repository2, "alice");
account2.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(1234L));
repository2.saveChanges();
}
repository1.discardChanges();
// Update account in 1
account1.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(5678L));
repository1.saveChanges();
}
}
}