forked from mirror/BlueMap
Small performance improvements (resolving world-ids and sql-querys)
This commit is contained in:
parent
057d25bd15
commit
44906f889b
@ -49,6 +49,7 @@
|
|||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.spongepowered.configurate.ConfigurateException;
|
import org.spongepowered.configurate.ConfigurateException;
|
||||||
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||||
import org.spongepowered.configurate.loader.HeaderMode;
|
import org.spongepowered.configurate.loader.HeaderMode;
|
||||||
|
|
||||||
@ -59,6 +60,7 @@
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,13 +83,13 @@ public BlueMapService(ServerInterface serverInterface, BlueMapConfigProvider con
|
|||||||
this.serverInterface = serverInterface;
|
this.serverInterface = serverInterface;
|
||||||
this.configs = configProvider;
|
this.configs = configProvider;
|
||||||
|
|
||||||
this.worldIds = new HashMap<>();
|
this.worldIds = new ConcurrentHashMap<>();
|
||||||
this.storages = new HashMap<>();
|
this.storages = new HashMap<>();
|
||||||
|
|
||||||
StateDumper.global().register(this);
|
StateDumper.global().register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized String getWorldId(Path worldFolder) throws IOException {
|
public String getWorldId(Path worldFolder) throws IOException {
|
||||||
// fast-path
|
// fast-path
|
||||||
String id = worldIds.get(worldFolder);
|
String id = worldIds.get(worldFolder);
|
||||||
if (id != null) return id;
|
if (id != null) return id;
|
||||||
@ -102,22 +104,29 @@ public synchronized String getWorldId(Path worldFolder) throws IOException {
|
|||||||
id = worldIds.get(worldFolder);
|
id = worldIds.get(worldFolder);
|
||||||
if (id != null) return id;
|
if (id != null) return id;
|
||||||
|
|
||||||
// now we can be sure it wasn't loaded yet .. load
|
synchronized (this) {
|
||||||
|
// check again if another thread has already added the world
|
||||||
|
id = worldIds.get(worldFolder);
|
||||||
|
if (id != null) return id;
|
||||||
|
|
||||||
Path idFile = worldFolder.resolve("bluemap.id");
|
Logger.global.logDebug("Loading world id for '" + worldFolder + "'...");
|
||||||
if (!Files.exists(idFile)) {
|
|
||||||
id = this.serverInterface.getWorld(worldFolder)
|
|
||||||
.flatMap(ServerWorld::getId)
|
|
||||||
.orElse(UUID.randomUUID().toString());
|
|
||||||
Files.writeString(idFile, id, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
|
||||||
|
|
||||||
|
// now we can be sure it wasn't loaded yet .. load
|
||||||
|
Path idFile = worldFolder.resolve("bluemap.id");
|
||||||
|
if (!Files.exists(idFile)) {
|
||||||
|
id = this.serverInterface.getWorld(worldFolder)
|
||||||
|
.flatMap(ServerWorld::getId)
|
||||||
|
.orElse(UUID.randomUUID().toString());
|
||||||
|
Files.writeString(idFile, id, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
|
||||||
|
worldIds.put(worldFolder, id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = Files.readString(idFile);
|
||||||
worldIds.put(worldFolder, id);
|
worldIds.put(worldFolder, id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = Files.readString(idFile);
|
|
||||||
worldIds.put(worldFolder, id);
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void createOrUpdateWebApp(boolean force) throws ConfigurationException {
|
public synchronized void createOrUpdateWebApp(boolean force) throws ConfigurationException {
|
||||||
@ -217,12 +226,13 @@ private synchronized void loadWorldsAndMaps() throws ConfigurationException, Int
|
|||||||
maps.put(id, map);
|
maps.put(id, map);
|
||||||
|
|
||||||
// load marker-config by converting it first from hocon to json and then loading it with MarkerGson
|
// load marker-config by converting it first from hocon to json and then loading it with MarkerGson
|
||||||
if (!mapConfig.getMarkerSets().empty()) {
|
ConfigurationNode markerSetNode = mapConfig.getMarkerSets();
|
||||||
|
if (markerSetNode != null && !markerSetNode.empty()) {
|
||||||
String markerJson = GsonConfigurationLoader.builder()
|
String markerJson = GsonConfigurationLoader.builder()
|
||||||
.headerMode(HeaderMode.NONE)
|
.headerMode(HeaderMode.NONE)
|
||||||
.lenient(false)
|
.lenient(false)
|
||||||
.indent(0)
|
.indent(0)
|
||||||
.buildAndSaveString(mapConfig.getMarkerSets());
|
.buildAndSaveString(markerSetNode);
|
||||||
Gson gson = MarkerGson.addAdapters(new GsonBuilder())
|
Gson gson = MarkerGson.addAdapters(new GsonBuilder())
|
||||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
|
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
|
||||||
.create();
|
.create();
|
||||||
@ -257,6 +267,8 @@ public synchronized Storage getStorage(String storageId) throws ConfigurationExc
|
|||||||
"You will either need to define that storage, or change the map-config to use a storage-config that exists.");
|
"You will either need to define that storage, or change the map-config to use a storage-config that exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.global.logInfo("Initializing Storage: '" + storageId + "' (Type: " + storageConfig.getStorageType() + ")");
|
||||||
|
|
||||||
storage = storageConfig.createStorage();
|
storage = storageConfig.createStorage();
|
||||||
storage.initialize();
|
storage.initialize();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -538,34 +538,28 @@ private void recoveringConnection(ConnectionConsumer action, int tries) throws S
|
|||||||
@SuppressWarnings("SameParameterValue")
|
@SuppressWarnings("SameParameterValue")
|
||||||
private <R> R recoveringConnection(ConnectionFunction<R> action, int tries) throws SQLException, IOException {
|
private <R> R recoveringConnection(ConnectionFunction<R> action, int tries) throws SQLException, IOException {
|
||||||
SQLException sqlException = null;
|
SQLException sqlException = null;
|
||||||
for (int i = 0; i < tries; i++) {
|
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
|
||||||
connection.setAutoCommit(false);
|
|
||||||
|
|
||||||
R result;
|
try {
|
||||||
try {
|
for (int i = 0; i < tries; i++) {
|
||||||
result = action.apply(connection);
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
connection.commit();
|
R result;
|
||||||
} catch (SQLRecoverableException ex) {
|
try {
|
||||||
connection.rollback();
|
result = action.apply(connection);
|
||||||
if (sqlException == null) {
|
connection.commit();
|
||||||
sqlException = ex;
|
return result;
|
||||||
} else {
|
} catch (SQLRecoverableException ex) {
|
||||||
sqlException.addSuppressed(ex);
|
if (sqlException == null) {
|
||||||
|
sqlException = ex;
|
||||||
|
} else {
|
||||||
|
sqlException.addSuppressed(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
} catch (SQLException | RuntimeException ex) {
|
|
||||||
connection.rollback();
|
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.setAutoCommit(true);
|
|
||||||
return result;
|
|
||||||
} catch (SQLException | IOException | RuntimeException ex) {
|
|
||||||
if (sqlException != null)
|
|
||||||
ex.addSuppressed(sqlException);
|
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
|
} catch (SQLException | IOException | RuntimeException ex) {
|
||||||
|
if (sqlException != null)
|
||||||
|
ex.addSuppressed(sqlException);
|
||||||
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert sqlException != null; // should never be null if we end up here
|
assert sqlException != null; // should never be null if we end up here
|
||||||
@ -680,9 +674,16 @@ private DataSource createDataSource(String dbUrl, String user, String password,
|
|||||||
|
|
||||||
private DataSource createDataSource(ConnectionFactory connectionFactory) {
|
private DataSource createDataSource(ConnectionFactory connectionFactory) {
|
||||||
PoolableConnectionFactory poolableConnectionFactory =
|
PoolableConnectionFactory poolableConnectionFactory =
|
||||||
new PoolableConnectionFactory(connectionFactory, null);
|
new PoolableConnectionFactory(() -> {
|
||||||
|
Logger.global.logDebug("Creating new SQL-Connection...");
|
||||||
|
return connectionFactory.createConnection();
|
||||||
|
}, null);
|
||||||
poolableConnectionFactory.setPoolStatements(true);
|
poolableConnectionFactory.setPoolStatements(true);
|
||||||
poolableConnectionFactory.setMaxOpenPreparedStatements(20);
|
poolableConnectionFactory.setMaxOpenPreparedStatements(20);
|
||||||
|
poolableConnectionFactory.setDefaultAutoCommit(false);
|
||||||
|
poolableConnectionFactory.setAutoCommitOnReturn(false);
|
||||||
|
poolableConnectionFactory.setRollbackOnReturn(true);
|
||||||
|
poolableConnectionFactory.setFastFailValidation(true);
|
||||||
|
|
||||||
GenericObjectPoolConfig<PoolableConnection> objectPoolConfig = new GenericObjectPoolConfig<>();
|
GenericObjectPoolConfig<PoolableConnection> objectPoolConfig = new GenericObjectPoolConfig<>();
|
||||||
objectPoolConfig.setMinIdle(1);
|
objectPoolConfig.setMinIdle(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user