Commit 430a0630 authored by Luna Riegel's avatar Luna Riegel
Browse files

Feat: Implement in-memory and fallback of database

Adds the handling and creation of the embedded database in RAM, which is
used for the in-memory and fallback modes.
parent 99763e56
package de.hft.stuttgart.citydoctor2.database;
import java.io.File;
import java.util.StringJoiner;
/**
* Record containing the configuration parameters for the setup of the embedded database
......@@ -20,8 +21,10 @@ import java.io.File;
public record EmbeddedDatabaseConfiguration(String databaseName, String databaseDirectory, int connectionPoolSize,
boolean inMemoryMode, boolean attemptFallback, boolean debugMode, boolean tempFileMode) {
private static final String IN_MEMORY_PREFIX= "mem:";
private static final String AUTO_SERVER_PARAMETER = ";AUTO_SERVER=TRUE";
private static final String IN_MEMORY_PREFIX = "mem:";
private static final String JDBC_DRIVER_PREFIX = "jdbc:h2:";
private static final String AUTO_SERVER_PARAMETER = "AUTO_SERVER=TRUE";
private static final String KEEP_ALIVE_PARAMETER = "DB_CLOSE_DELAY=-1";
private static final String FILE_PREFIX = "file://";
/**
* Instantiates the default configuration for the embedded database.
......@@ -36,20 +39,31 @@ public record EmbeddedDatabaseConfiguration(String databaseName, String database
true, true, true, false);
}
public String wrapUrlWithH2JdbcDriver(String Url){
return JDBC_DRIVER_PREFIX + Url + getH2ParametersSuffix();
}
public String getInMemoryH2Url() {
return IN_MEMORY_PREFIX + databaseName;
return wrapUrlWithH2JdbcDriver(IN_MEMORY_PREFIX + databaseName);
}
public String getFallbackH2Url(){
return getInMemoryH2Url() + ";" + KEEP_ALIVE_PARAMETER;
}
public String getH2FileUrl(){
return FILE_PREFIX + databaseDirectory + databaseName;
return wrapUrlWithH2JdbcDriver(databaseDirectory + databaseName);
}
public String getH2ParametersSuffix(){
StringJoiner joiner = new StringJoiner(";",";","");
if (debugMode){
return AUTO_SERVER_PARAMETER;
} else {
return ";";
joiner.add(AUTO_SERVER_PARAMETER);
}
if (inMemoryMode){
joiner.add(KEEP_ALIVE_PARAMETER);
}
return joiner.toString();
}
}
......@@ -14,10 +14,9 @@ import org.apache.commons.lang3.SerializationException;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.h2gis.functions.factory.H2GISDBFactory;
import org.h2gis.utilities.wrapper.DataSourceWrapper;
import org.h2gis.functions.factory.H2GISFunctions;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
......@@ -26,6 +25,7 @@ import java.io.InvalidClassException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
......@@ -41,20 +41,21 @@ public class EmbeddedDatabaseHandler {
private static final Logger logger = LogManager.getLogger(EmbeddedDatabaseHandler.class);
private final EmbeddedDatabaseConfiguration config;
private DataSourceWrapper dataSource;
private File tempLoc = null;
private File tempFileDBLocation = null;
public EmbeddedDatabaseHandler(EmbeddedDatabaseConfiguration dbConfig){
config = dbConfig;
String jdbcUrl;
try {
if (config.inMemoryMode()) {
jdbcUrl = createEmbeddedDataBase(config.getInMemoryH2Url());
jdbcUrl = setupInMemoryDataBase(config.getInMemoryH2Url());
} else if (config.tempFileMode()){
Path tmpDir = Files.createTempDirectory(config.databaseDirectory());
tmpDir.toFile().deleteOnExit();
String tempFileUrl = tmpDir.resolve(config.databaseName()).toFile().getAbsolutePath();
jdbcUrl = createEmbeddedDataBase(tempFileUrl);
tempLoc = new File(tempFileUrl);
String tempFileUrl = tmpDir.resolve(config.databaseName()).toFile().getCanonicalPath();
jdbcUrl = createEmbeddedDataBase(config.wrapUrlWithH2JdbcDriver(tempFileUrl));
tempFileDBLocation = new File(tempFileUrl+".mv.db");
tempFileDBLocation.deleteOnExit();
} else {
jdbcUrl = createEmbeddedDataBase(config.getH2FileUrl());
}
......@@ -66,7 +67,7 @@ public class EmbeddedDatabaseHandler {
if (config.attemptFallback()){
logger.info("Attempting fallback to in-memory database");
try {
jdbcUrl = createEmbeddedDataBase(config.getInMemoryH2Url());
jdbcUrl = setupInMemoryDataBase(config.getFallbackH2Url());
} catch (Exception e1) {
throw new EmbeddedDatabaseHandlerException("Fallback to in-memory database failed, embedded database could not be created", e1);
}
......@@ -93,15 +94,26 @@ public class EmbeddedDatabaseHandler {
}
private String createEmbeddedDataBase(String dbUrl) throws SQLException {
DataSource source = H2GISDBFactory.createDataSource(dbUrl,
true, config.getH2ParametersSuffix());
try (Connection con = source.getConnection()) {
// DataSource source = H2GISDBFactory.createDataSource("file://"+dbUrl,
// true, config.getH2ParametersSuffix());
// try (Connection con = source.getConnection()) {
// return con.getMetaData().getURL();
// }
try (Connection con = DriverManager.getConnection(dbUrl,"sa","sa")){
H2GISFunctions.load(con);
return con.getMetaData().getURL();
}
}
public File getTempLoc(){
return this.tempLoc;
private String setupInMemoryDataBase(String dbUrl) throws SQLException{
try (Connection con = DriverManager.getConnection(dbUrl,"sa","sa")){
H2GISFunctions.load(con);
return con.getMetaData().getURL();
}
}
public File getTempFileDBLocation(){
return this.tempFileDBLocation;
}
......
......@@ -16,7 +16,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.model.building.AbstractBuilding;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
......@@ -33,37 +32,38 @@ import static org.junit.Assert.fail;
public class EmbeddedDataBaseHandlerTest {
private EmbeddedDatabaseHandler handler = new EmbeddedDatabaseHandler(new EmbeddedDatabaseConfiguration());
@Before
public void resetDatabase() {
try {
handler.setupFeaturesTable();
} catch (Exception e) {
fail(e.getMessage());
}
}
//TODO: FIX Test failures
@Test
public void testTempFileConfiguration(){
EmbeddedDatabaseConfiguration tempFileconfig = new EmbeddedDatabaseConfiguration("database",
"inTempConfig",1, false,false,
false,true);
assertNull(handler.getTempLoc());
EmbeddedDatabaseHandler tempHandler = new EmbeddedDatabaseHandler(tempFileconfig);
assertTrue(tempHandler.getTempLoc().exists());
assertTrue(tempHandler.getTempFileDBLocation().exists());
}
@Test
public void testInMemoryConfiguration(){
public void testInMemoryConfiguration() throws CityGmlParseException, InvalidGmlFileException {
EmbeddedDatabaseConfiguration inMemoryConfig = new EmbeddedDatabaseConfiguration("database",
"irrelevant",1, true,false,
false,false);
EmbeddedDatabaseHandler memHandler = new EmbeddedDatabaseHandler(inMemoryConfig);
assertFalse(memHandler.getTempLoc().exists());
assertNull(memHandler.getTempFileDBLocation());
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = CityGmlParser.nestedCityGmlFileParse("src/test/resources/SimpleSolid_SrefBS.gml", config);
Building b = model.getBuildings().toList().get(0);
assertEquals(0, memHandler.getFeatureCount());
memHandler.marshallCityObject(b);
assertEquals(1, memHandler.getFeatureCount());
CityObject co = memHandler.unmarshallCityObject(b.getGmlId());
assertNotNull(co);
assertTrue(co instanceof Building);
}
@Test
public void testGetBboxIntersectingObjects() {
handler.setupFeaturesTable();
Building b = new Building();
Building b2 = new Building();
b2.setGmlObject(Mockito.mock(AbstractBuilding.class));
......@@ -144,6 +144,7 @@ public class EmbeddedDataBaseHandlerTest {
@Test
public void testGetBboxBufferIntersectingObjects() {
handler.setupFeaturesTable();
Building b = new Building();
Building b2 = new Building();
b2.setGmlObject(Mockito.mock(AbstractBuilding.class));
......@@ -230,6 +231,7 @@ public class EmbeddedDataBaseHandlerTest {
Building b = model.getBuildings().toList().get(0);
assertNotNull(b);
assertEquals(1, handler.getFeatureCount());
handler.marshallCityObject(b);
assertEquals(1, handler.getFeatureCount());
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment