test database for blocks db

master
Thomas Rudin 2018-12-14 17:02:52 +01:00
parent 783f761860
commit 308b170baa
10 changed files with 144 additions and 115 deletions

View File

@ -2,6 +2,7 @@ package io.rudin.minetest.tileserver.config;
import org.aeonbits.owner.Config;
import org.aeonbits.owner.Config.Sources;
import org.jooq.SQLDialect;
@Sources({
"file:./tileserver.properties"
@ -140,6 +141,10 @@ public interface TileServerConfig extends Config {
@DefaultValue("org.postgresql.Driver")
String minetestDatabaseDriver();
@Key("minetest.db.dialect")
@DefaultValue("POSTGRES")
SQLDialect minetestDatabaseDialect();
/*
Tile cache DB
*/

View File

@ -28,7 +28,7 @@ public class MapDBDSLContextProvider implements Provider<DSLContext> {
@Override
public DSLContext get() {
return DSL.using(ds, SQLDialect.POSTGRES);
return DSL.using(ds, cfg.minetestDatabaseDialect());
}
}

View File

@ -14,22 +14,21 @@ public class MapDBDatasourceProvider implements Provider<DataSource> {
@Inject
public MapDBDatasourceProvider(TileServerConfig cfg) {
this.cfg = cfg;
}
private final TileServerConfig cfg;
@Override
@Singleton
public DataSource get() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setUsername(cfg.minetestDatabaseUsername());
hikariConfig.setPassword(cfg.minetestDatabasePassword());
hikariConfig.setJdbcUrl(cfg.minetestDatabaseUrl());
hikariConfig.setDriverClassName(cfg.minetestDatabaseDriver());
return new HikariDataSource(hikariConfig);
ds = new HikariDataSource(hikariConfig);
}
private final HikariDataSource ds;
@Override
@Singleton
public DataSource get() {
return ds;
}
}

View File

@ -15,22 +15,21 @@ public class TileDBDatasourceProvider implements Provider<DataSource> {
@Inject
public TileDBDatasourceProvider(TileServerConfig cfg) {
this.cfg = cfg;
}
private final TileServerConfig cfg;
@Override
@Singleton
public DataSource get() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setUsername(cfg.tileDatabaseUsername());
hikariConfig.setPassword(cfg.tileDatabasePassword());
hikariConfig.setJdbcUrl(cfg.tileDatabaseUrl());
hikariConfig.setDriverClassName(cfg.tileDatabaseDriver());
return new HikariDataSource(hikariConfig);
this.ds = new HikariDataSource(hikariConfig);
}
private final HikariDataSource ds;
@Override
@Singleton
public DataSource get() {
return ds;
}
}

View File

@ -0,0 +1,54 @@
package io.rudin.minetest.tileserver;
import io.rudin.minetest.tileserver.accessor.Coordinate;
import io.rudin.minetest.tileserver.base.TileServerTest;
import io.rudin.minetest.tileserver.blockdb.tables.Blocks;
import io.rudin.minetest.tileserver.blockdb.tables.records.BlocksRecord;
import io.rudin.minetest.tileserver.job.UpdateChangedTilesJob;
import io.rudin.minetest.tileserver.qualifier.MapDB;
import io.rudin.minetest.tileserver.service.BlocksRecordService;
import io.rudin.minetest.tileserver.service.TileCache;
import org.jooq.DSLContext;
import org.junit.Assert;
import org.junit.Test;
import javax.inject.Inject;
import java.io.IOException;
import java.util.List;
import static io.rudin.minetest.tileserver.blockdb.tables.Blocks.BLOCKS;
public class UpdateChangedTilesTest extends TileServerTest {
@Inject UpdateChangedTilesJob changedTilesJob;
@Inject TileCache tileCache;
@Inject @MapDB DSLContext ctx;
@Test
public void test() throws IOException {
byte[] tile = tileCache.get(0, 0, 1, 13);
Assert.assertNull(tile);
changedTilesJob.run();
tile = tileCache.get(0, 0, 1, 13);
Assert.assertNotNull(tile);
BlocksRecord block = ctx.selectFrom(BLOCKS)
.where(BLOCKS.POSX.eq(0).and(BLOCKS.POSY.eq(0).and(BLOCKS.POSZ.eq(0))))
.fetchOne();
block.setMtime(System.currentTimeMillis());
block.update();
changedTilesJob.run();
tile = tileCache.get(0, 0, 1, 13);
Assert.assertNotNull(tile);
}
}

View File

@ -5,31 +5,44 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import io.rudin.minetest.tileserver.DBMigration;
import io.rudin.minetest.tileserver.blockdb.tables.Blocks;
import io.rudin.minetest.tileserver.blockdb.tables.records.BlocksRecord;
import io.rudin.minetest.tileserver.config.TileServerConfig;
import io.rudin.minetest.tileserver.module.ConfigModule;
import io.rudin.minetest.tileserver.module.DBModule;
import io.rudin.minetest.tileserver.module.ServiceModule;
import io.rudin.minetest.tileserver.module.TestServiceModule;
import io.rudin.minetest.tileserver.qualifier.MapDB;
import io.rudin.minetest.tileserver.util.StreamUtil;
import org.aeonbits.owner.ConfigFactory;
import org.jooq.DSLContext;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import static io.rudin.minetest.tileserver.blockdb.tables.Blocks.BLOCKS;
public class TileServerTest {
private static Logger logger = LoggerFactory.getLogger(TileServerTest.class);
@Before
public void init() throws SQLException {
public void init() throws SQLException, IOException {
Map<String, String> properties = new HashMap<>();
properties.put("minetest.db.url", "jdbc:h2:mem:tileserver");
properties.put("minetest.db.url", "jdbc:h2:mem:tileserver;DB_CLOSE_DELAY=-1");
properties.put("minetest.db.username", "sa");
properties.put("minetest.db.password", "");
properties.put("minetest.db.driver", "org.h2.Driver");
properties.put("minetest.db.dialect", "H2");
TileServerConfig cfg = ConfigFactory.create(TileServerConfig.class, properties);
@ -43,16 +56,53 @@ public class TileServerTest {
try (Connection connection = dataSource.getConnection()){
connection.createStatement().execute("drop all objects");
connection.createStatement().execute("runscript from 'classpath:/minetest-db.sql'");
}
//does not work: create function plsql not available in h2
//injector.getInstance(DBMigration.class).migrate();
uploadMapBlocksToDatabase();
logger.info("Environment set up, injecting members");
injector.injectMembers(this);
}
private Injector injector;
private void uploadMapBlocksToDatabase() throws IOException {
DSLContext ctx = injector.getInstance(Key.get(DSLContext.class, MapDB.class));
File mapBlockDir = new File("testdata/mapblocks");
for (File file: mapBlockDir.listFiles()){
if (file.getName().startsWith("."))
continue;
String[] parts = file.getName().split("[.]");
int posx = Integer.parseInt(parts[0]);
int posy = Integer.parseInt(parts[1]);
int posz = Integer.parseInt(parts[2]);
ByteArrayOutputStream data = new ByteArrayOutputStream();
try (InputStream input = new FileInputStream(file)){
StreamUtil.copyStream(input, data);
}
BlocksRecord record = ctx.newRecord(BLOCKS);
record.setMtime(System.currentTimeMillis());
record.setPosy(posy);
record.setPosx(posx);
record.setPosz(posz);
record.setData(data.toByteArray());
record.insert();
}
}
@After
public void after(){
}

View File

@ -7,10 +7,7 @@ import io.rudin.minetest.tileserver.config.TileServerConfig;
import io.rudin.minetest.tileserver.provider.ColorTableProvider;
import io.rudin.minetest.tileserver.provider.ExecutorProvider;
import io.rudin.minetest.tileserver.provider.LayerConfigProvider;
import io.rudin.minetest.tileserver.service.BlocksRecordLocalService;
import io.rudin.minetest.tileserver.service.BlocksRecordService;
import io.rudin.minetest.tileserver.service.EventBus;
import io.rudin.minetest.tileserver.service.TileCache;
import io.rudin.minetest.tileserver.service.*;
import io.rudin.minetest.tileserver.service.impl.*;
import java.util.concurrent.ExecutorService;
@ -28,7 +25,8 @@ public class TestServiceModule extends AbstractModule {
bind(ExecutorService.class).toProvider(ExecutorProvider.class);
bind(ScheduledExecutorService.class).toProvider(ExecutorProvider.class);
bind(LayerConfig.class).toProvider(LayerConfigProvider.class);
bind(MapBlockRenderService.class).to(DefaultMapBlockRenderService.class);
bind(BlocksRecordService.class).to(BlocksRecordLocalService.class);
bind(BlocksRecordService.class).to(BlocksRecordDatabaseService.class);
}
}

View File

@ -1,80 +0,0 @@
package io.rudin.minetest.tileserver.service;
import io.rudin.minetest.tileserver.accessor.Coordinate;
import io.rudin.minetest.tileserver.blockdb.tables.records.BlocksRecord;
import io.rudin.minetest.tileserver.service.impl.BlocksRecordDatabaseService;
import io.rudin.minetest.tileserver.util.StreamUtil;
import sun.security.action.OpenFileInputStreamAction;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
public class BlocksRecordLocalService implements BlocksRecordService {
private final Map<Coordinate, BlocksRecord> cache = new HashMap<>();
@Override
public List<BlocksRecord> getTopDownYStride(int x, int z, int minY, int maxY) {
List<BlocksRecord> result = new ArrayList<>();
for (int y=minY; y<=maxY; y++){
Coordinate coordinate = new Coordinate(x, y, z);
Optional<BlocksRecord> optionalRecord = get(coordinate);
if (optionalRecord.isPresent())
result.add(optionalRecord.get());
}
result.sort(Comparator.comparingInt(BlocksRecord::getPosy));
return result;
}
public static File getLocalMapBlockFile(Coordinate coordinate){
File mapblockDir = new File("testdata/mapblocks");
if (!mapblockDir.isDirectory())
mapblockDir.mkdir();
return new File(mapblockDir, coordinate.x + "." + coordinate.y + "." + coordinate.z);
}
@Override
public Optional<BlocksRecord> get(Coordinate coords) {
BlocksRecord record = cache.get(coords);
if (record != null)
return Optional.of(record);
File file = getLocalMapBlockFile(coords);
if (!file.isFile())
return Optional.empty();
try (InputStream input = new FileInputStream(file)){
ByteArrayOutputStream output = new ByteArrayOutputStream();
StreamUtil.copyStream(input, output);
record = new BlocksRecord();
record.setData(output.toByteArray());
record.setMtime(file.lastModified());
record.setPosx(coords.x);
record.setPosy(coords.y);
record.setPosz(coords.z);
cache.put(coords, record);
return Optional.of(record);
} catch (Exception e){
throw new IllegalArgumentException(e);
}
}
@Override
public void update(BlocksRecord block) {
cache.put(new Coordinate(block), block);
}
}

View File

@ -15,4 +15,7 @@
<appender-ref ref="console" />
</root>
<logger name="org.jooq" level="info">
</logger>
</configuration>

View File

@ -1,9 +1,10 @@
create table blocks(
posx int not null,
posy int not null,
posz int not null,
data bytea,
create table "blocks"(
"posx" int not null,
"posy" int not null,
"posz" int not null,
"data" bytea,
"mtime" bigint not null default 0,
PRIMARY KEY(posx,posy,posz)
);
PRIMARY KEY("posx","posy","posz")
);