Throw an exception if the file handler can't read/write to the DB
This commit is contained in:
@@ -80,11 +80,6 @@ public abstract class AbstractDataSourceHandler
|
||||
{
|
||||
this.level = level;
|
||||
this.saveDir = (saveDirOverride == null) ? saveStructure.getFullDataFolder(level.getLevelWrapper()) : saveDirOverride;
|
||||
if (!this.saveDir.exists() && !this.saveDir.mkdirs())
|
||||
{
|
||||
LOGGER.warn("Unable to create full data folder, file saving may fail.");
|
||||
}
|
||||
|
||||
this.repo = this.createRepo();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class FullDataSourceProviderV1<TDhLevel extends IDhLevel>
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FullDataSourceV1Repo("jdbc:sqlite", this.saveDir.getPath() + "/" + AbstractSaveStructure.DATABASE_NAME);
|
||||
return new FullDataSourceV1Repo("jdbc:sqlite", new File(this.saveDir.getPath() + File.pathSeparator + AbstractSaveStructure.DATABASE_NAME));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ public class FullDataSourceProviderV2
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FullDataSourceV2Repo("jdbc:sqlite", this.saveDir.getPath() + "/" + AbstractSaveStructure.DATABASE_NAME);
|
||||
return new FullDataSourceV2Repo("jdbc:sqlite", new File(this.saveDir.getPath() + File.pathSeparator + AbstractSaveStructure.DATABASE_NAME));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -59,12 +60,12 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
|
||||
protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); }
|
||||
|
||||
protected void createAndSetChunkHashRepo(String databaseFilePath)
|
||||
protected void createAndSetChunkHashRepo(File databaseFile)
|
||||
{
|
||||
ChunkHashRepo newChunkHashRepo = null;
|
||||
try
|
||||
{
|
||||
newChunkHashRepo = new ChunkHashRepo("jdbc:sqlite", databaseFilePath);
|
||||
newChunkHashRepo = new ChunkHashRepo("jdbc:sqlite", databaseFile);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -63,7 +62,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride);
|
||||
this.clientside = new ClientLevelModule(this);
|
||||
|
||||
this.createAndSetChunkHashRepo(this.dataFileHandler.repo.databaseLocation);
|
||||
this.createAndSetChunkHashRepo(this.dataFileHandler.repo.databaseFile);
|
||||
|
||||
if (enableRendering)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -69,7 +68,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
|
||||
this.serverLevelWrapper = serverLevelWrapper;
|
||||
this.serverside = new ServerLevelModule(this, saveStructure);
|
||||
this.clientside = new ClientLevelModule(this);
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseLocation);
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
|
||||
LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -48,7 +47,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
|
||||
}
|
||||
this.serverLevelWrapper = serverLevelWrapper;
|
||||
this.serverside = new ServerLevelModule(this, saveStructure);
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseLocation);
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
|
||||
LOGGER.info("Started DHLevel for {} with saves at {}", serverLevelWrapper, saveStructure);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class DatabaseUpdater
|
||||
Map<String, Object> scriptAlreadyRunResult = repo.queryDictionaryFirst("SELECT EXISTS(SELECT 1 FROM "+SCHEMA_TABLE_NAME+" WHERE ScriptName='"+resource.name+"') as 'existingCount';");
|
||||
if (scriptAlreadyRunResult != null && (int) scriptAlreadyRunResult.get("existingCount") == 0)
|
||||
{
|
||||
LOGGER.info("Running SQL update script: ["+resource.name+"], for repo: ["+repo.databaseLocation+"]");
|
||||
LOGGER.info("Running SQL update script: ["+resource.name+"], for repo: ["+repo.databaseFile +"]");
|
||||
|
||||
|
||||
int sqlIndex = 0;
|
||||
@@ -147,7 +147,7 @@ public class DatabaseUpdater
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
// updating needs to stop to prevent data corruption
|
||||
LOGGER.error("Unexpected error running database update script ["+resource.name+"] on database ["+repo.databaseLocation+"], stopping database update. Database reading/writing may fail if you continue. \n" +
|
||||
LOGGER.error("Unexpected error running database update script ["+resource.name+"] on database ["+repo.databaseFile +"], stopping database update. Database reading/writing may fail if you continue. \n" +
|
||||
"Error: ["+e.getMessage()+"]. \n" +
|
||||
"Sql Script:["+resource.queryString+"]", e);
|
||||
throw e;
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.seibel.distanthorizons.core.sql.dto.IBaseDTO;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -49,7 +51,7 @@ public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>> implemen
|
||||
private final Connection connection;
|
||||
|
||||
public final String databaseType;
|
||||
public final String databaseLocation;
|
||||
public final File databaseFile;
|
||||
|
||||
public final Class<? extends TDTO> dtoClass;
|
||||
|
||||
@@ -59,16 +61,15 @@ public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>> implemen
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
/** @throws SQLException if the repo is unable to access the database or has trouble updating said database. */
|
||||
public AbstractDhRepo(String databaseType, String databaseLocation, Class<? extends TDTO> dtoClass) throws SQLException
|
||||
public AbstractDhRepo(String databaseType, File databaseFile, Class<? extends TDTO> dtoClass) throws SQLException
|
||||
{
|
||||
this.databaseType = databaseType;
|
||||
this.databaseLocation = databaseLocation;
|
||||
this.databaseFile = databaseFile;
|
||||
this.dtoClass = dtoClass;
|
||||
|
||||
|
||||
@@ -93,9 +94,55 @@ public abstract class AbstractDhRepo<TKey, TDTO extends IBaseDTO<TKey>> implemen
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// database file validation //
|
||||
//==========================//
|
||||
|
||||
// check that the database file exists
|
||||
if (!databaseFile.exists())
|
||||
{
|
||||
// check that the parent folder exists
|
||||
File parentFolder = databaseFile.getParentFile();
|
||||
if (parentFolder != null && !parentFolder.exists())
|
||||
{
|
||||
if (!parentFolder.mkdirs())
|
||||
{
|
||||
throw new RuntimeException("Unable to create the necessary parent folders for the database file at location ["+databaseFile.getPath()+"].");
|
||||
}
|
||||
}
|
||||
|
||||
if (!databaseFile.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean fileCreated = databaseFile.createNewFile();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to create database file at location ["+databaseFile.getPath()+"] due to error: ["+e.getMessage()+"]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!databaseFile.canRead())
|
||||
{
|
||||
throw new RuntimeException("Unable to read database file at location ["+databaseFile.getPath()+"], please make sure the folder and file has the correct permissions.");
|
||||
}
|
||||
if (!databaseFile.canWrite())
|
||||
{
|
||||
throw new RuntimeException("Unable to write database file at location ["+databaseFile.getPath()+"], please make sure the folder and file aren't set to read-only.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// connection setup //
|
||||
//==================//
|
||||
|
||||
// get or create the connection,
|
||||
// reusing existing connections reduces the chance of locking the database during trivial queries
|
||||
this.connectionString = this.databaseType+":"+this.databaseLocation;
|
||||
this.connectionString = this.databaseType+":"+this.databaseFile.getPath();
|
||||
|
||||
|
||||
this.connection = CONNECTIONS_BY_CONNECTION_STRING.computeIfAbsent(this.connectionString, (connectionString) ->
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
@@ -40,9 +41,9 @@ public class ChunkHashRepo extends AbstractDhRepo<DhChunkPos, ChunkHashDTO>
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public ChunkHashRepo(String databaseType, String databaseLocation) throws SQLException
|
||||
public ChunkHashRepo(String databaseType, File databaseFile) throws SQLException
|
||||
{
|
||||
super(databaseType, databaseLocation, ChunkHashDTO.class);
|
||||
super(databaseType, databaseFile, ChunkHashDTO.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -26,6 +26,7 @@ import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@@ -42,9 +43,9 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<Long, FullDataSourceV1D
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public FullDataSourceV1Repo(String databaseType, String databaseLocation) throws SQLException
|
||||
public FullDataSourceV1Repo(String databaseType, File databaseFile) throws SQLException
|
||||
{
|
||||
super(databaseType, databaseLocation, FullDataSourceV1DTO.class);
|
||||
super(databaseType, databaseFile, FullDataSourceV1DTO.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
@@ -45,9 +46,9 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<Long, FullDataSourceV2D
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public FullDataSourceV2Repo(String databaseType, String databaseLocation) throws SQLException
|
||||
public FullDataSourceV2Repo(String databaseType, File databaseFile) throws SQLException
|
||||
{
|
||||
super(databaseType, databaseLocation, FullDataSourceV2DTO.class);
|
||||
super(databaseType, databaseFile, FullDataSourceV2DTO.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ package testItems.sql;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
@@ -29,9 +30,9 @@ import java.util.Map;
|
||||
public class TestCompoundKeyRepo extends AbstractDhRepo<DhChunkPos, TestCompoundKeyDto>
|
||||
{
|
||||
|
||||
public TestCompoundKeyRepo(String databaseType, String databaseLocation) throws SQLException
|
||||
public TestCompoundKeyRepo(String databaseType, File databaseFile) throws SQLException
|
||||
{
|
||||
super(databaseType, databaseLocation, TestCompoundKeyDto.class);
|
||||
super(databaseType, databaseFile, TestCompoundKeyDto.class);
|
||||
|
||||
// note: this should only ever be done with the test repo.
|
||||
// All long term tables should be created using a sql Script.
|
||||
|
||||
@@ -21,6 +21,7 @@ package testItems.sql;
|
||||
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
@@ -28,9 +29,9 @@ import java.util.Map;
|
||||
public class TestPrimaryKeyRepo extends AbstractDhRepo<Integer, TestSingleKeyDto>
|
||||
{
|
||||
|
||||
public TestPrimaryKeyRepo(String databaseType, String databaseLocation) throws SQLException
|
||||
public TestPrimaryKeyRepo(String databaseType, File databaseFile) throws SQLException
|
||||
{
|
||||
super(databaseType, databaseLocation, TestSingleKeyDto.class);
|
||||
super(databaseType, databaseFile, TestSingleKeyDto.class);
|
||||
|
||||
// note: this should only ever be done with the test repo.
|
||||
// All long term tables should be created using a sql Script.
|
||||
|
||||
@@ -259,7 +259,7 @@ public class CompressionTest
|
||||
File uncompressedDatabaseFile = new File(uncompressedDatabaseFilePath);
|
||||
Assert.assertTrue(uncompressedDatabaseFile.exists());
|
||||
|
||||
FullDataSourceV2Repo uncompressedRepo = new FullDataSourceV2Repo("jdbc:sqlite", uncompressedDatabaseFilePath);
|
||||
FullDataSourceV2Repo uncompressedRepo = new FullDataSourceV2Repo("jdbc:sqlite", uncompressedDatabaseFile);
|
||||
|
||||
|
||||
String compressedDatabaseFilePath = TEST_DIR + "/output/" + DB_FILE_NAME_PREFIX + "_" + compressorName + ".sqlite";
|
||||
@@ -267,7 +267,7 @@ public class CompressionTest
|
||||
compressedDatabaseFile.mkdirs();
|
||||
compressedDatabaseFile.delete();
|
||||
Assert.assertTrue(!compressedDatabaseFile.exists());
|
||||
FullDataSourceV2Repo compressedRepo = new FullDataSourceV2Repo("jdbc:sqlite", compressedDatabaseFilePath);
|
||||
FullDataSourceV2Repo compressedRepo = new FullDataSourceV2Repo("jdbc:sqlite", uncompressedDatabaseFile);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public class DhRepoSqliteTest
|
||||
TestPrimaryKeyRepo primaryKeyRepo = null;
|
||||
try
|
||||
{
|
||||
primaryKeyRepo = new TestPrimaryKeyRepo(DATABASE_TYPE, DB_FILE_NAME);
|
||||
primaryKeyRepo = new TestPrimaryKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME));
|
||||
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ public class DhRepoSqliteTest
|
||||
}
|
||||
|
||||
// check that the update scripts aren't run multiple times
|
||||
TestPrimaryKeyRepo altDataRepoOne = new TestPrimaryKeyRepo(DATABASE_TYPE, DB_FILE_NAME);
|
||||
TestPrimaryKeyRepo altDataRepoTwo = new TestPrimaryKeyRepo(DATABASE_TYPE, DB_FILE_NAME);
|
||||
TestPrimaryKeyRepo altDataRepoOne = new TestPrimaryKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME));
|
||||
TestPrimaryKeyRepo altDataRepoTwo = new TestPrimaryKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME));
|
||||
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ public class DhRepoSqliteTest
|
||||
TestCompoundKeyRepo compoundKeyRepo = null;
|
||||
try
|
||||
{
|
||||
compoundKeyRepo = new TestCompoundKeyRepo(DATABASE_TYPE, DB_FILE_NAME);
|
||||
compoundKeyRepo = new TestCompoundKeyRepo(DATABASE_TYPE, new File(DB_FILE_NAME));
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user