diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java index dcfbda7d7..1e461b810 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java @@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.sql.dto.IBaseDTO; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; +import javax.swing.plaf.nimbus.State; import java.io.File; import java.io.IOException; import java.sql.*; @@ -180,7 +181,8 @@ public abstract class AbstractDhRepo> implemen public TDTO getByKey(TKey primaryKey) { - try(ResultSet resultSet = this.query(this.createSelectStatementByKey(primaryKey))) + try(PreparedStatement statement = this.createSelectStatementByKey(primaryKey); + ResultSet resultSet = this.query(statement)) { if (resultSet != null && resultSet.next()) { diff --git a/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java b/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java index 509af940d..177b375df 100644 --- a/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java +++ b/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java @@ -48,8 +48,10 @@ public class TestCompoundKeyRepo extends AbstractDhRepo[] futures = new CompletableFuture[poolSize]; + ThreadPoolExecutor pool = ThreadUtil.makeThreadPool(poolSize, "test pool"); + for (int threadIndex = 0; threadIndex < poolSize; threadIndex++) { - repo.save(originalDto); - try (FullDataSourceV2DTO pooledDto = repo.getByKey(pos)) + final int finalThreadIndex = threadIndex; + futures[threadIndex] = CompletableFuture.runAsync(() -> { - Assert.assertNotNull(savedDto); - Assert.assertEquals(originalDto.pos, savedDto.pos); - assertArraysAreEqual(originalDto.compressedDataByteArray, savedDto.compressedDataByteArray); - assertArraysAreEqual(originalDto.compressedColumnGenStepByteArray, savedDto.compressedColumnGenStepByteArray); - assertArraysAreEqual(originalDto.compressedWorldCompressionModeByteArray, savedDto.compressedWorldCompressionModeByteArray); - } + // create a new DTO so each thread can have their own to work with, + // otherwise they'll get stuck on locks for interacting with the same row + FullDataSourceV2DTO threadDto = null; + try + { + threadDto = FullDataSourceV2DTO.CreateFromDataSource(originalDataSource, EDhApiDataCompressionMode.LZMA2); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + + // new position so each DTO is different and saved to a different row in the DB + long threadPos = DhSectionPos.encode((byte)0, finalThreadIndex, 0); + threadDto.pos = threadPos; + + // run for a long time + for (int j = 0; j < 1_000_000; j++) + { + repo.save(threadDto); // runs significantly faster if we don't save + + try (FullDataSourceV2DTO pooledDto = repo.getByKey(threadPos)) + { + Assert.assertNotNull(threadDto); + Assert.assertEquals(pooledDto.pos, threadDto.pos); + assertArraysAreEqual(pooledDto.compressedDataByteArray, threadDto.compressedDataByteArray); + assertArraysAreEqual(pooledDto.compressedColumnGenStepByteArray, threadDto.compressedColumnGenStepByteArray); + assertArraysAreEqual(pooledDto.compressedWorldCompressionModeByteArray, threadDto.compressedWorldCompressionModeByteArray); + } + } + }, pool); } + + CompletableFuture.allOf(futures).join(); } } catch (Exception e) @@ -176,13 +197,6 @@ public class DhFullDataSourceCacheTest e.printStackTrace(); Assert.fail(e.getMessage()); } - finally - { - if (repo != null) - { - repo.close(); - } - } } diff --git a/core/src/test/java/tests/DhRepoSqliteTest.java b/core/src/test/java/tests/DhRepoSqliteTest.java index ebd467ecf..a7be9091f 100644 --- a/core/src/test/java/tests/DhRepoSqliteTest.java +++ b/core/src/test/java/tests/DhRepoSqliteTest.java @@ -31,6 +31,7 @@ import testItems.sql.TestPrimaryKeyRepo; import testItems.sql.TestSingleKeyDto; import java.io.File; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; @@ -72,14 +73,19 @@ public class DhRepoSqliteTest //==========================// // check that the schema table is created - ResultSet autoUpdateTablePresentResult = primaryKeyRepo.query(primaryKeyRepo.createPreparedStatement("SELECT name FROM sqlite_master WHERE type='table' AND name='"+DatabaseUpdater.SCHEMA_TABLE_NAME+"';")); - if (autoUpdateTablePresentResult == null - || !autoUpdateTablePresentResult.next() - || autoUpdateTablePresentResult.getString("name") == null) + try(PreparedStatement statement = primaryKeyRepo.createPreparedStatement( + "SELECT name FROM sqlite_master WHERE type='table' AND name='"+DatabaseUpdater.SCHEMA_TABLE_NAME+"';"); + ResultSet autoUpdateTablePresentResult = primaryKeyRepo.query(statement)) { - Assert.fail("Auto DB update table missing."); + if (autoUpdateTablePresentResult == null + || !autoUpdateTablePresentResult.next() + || autoUpdateTablePresentResult.getString("name") == null) + { + Assert.fail("Auto DB update table missing."); + } } + // check that the update scripts aren't run multiple times TestPrimaryKeyRepo altDataRepoOne = new TestPrimaryKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME)); TestPrimaryKeyRepo altDataRepoTwo = new TestPrimaryKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME));